[sql] Remove _HAS_EXCEPTIONS=0 from build info.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob7d7ad95028b55a080476e904cb28ea50aad37ca8
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 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
735 // check with all attached and enabled color attachments.
736 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
737 bool BoundFramebufferHasDepthAttachment();
738 bool BoundFramebufferHasStencilAttachment();
740 error::ContextLostReason GetContextLostReason() override;
742 // Overridden from FramebufferManager::TextureDetachObserver:
743 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
745 // Overriden from ErrorStateClient.
746 void OnContextLostError() override;
747 void OnOutOfMemoryError() override;
749 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
750 void EnsureRenderbufferBound();
752 // Helpers to facilitate calling into compatible extensions.
753 static void RenderbufferStorageMultisampleHelper(
754 const FeatureInfo* feature_info,
755 GLenum target,
756 GLsizei samples,
757 GLenum internal_format,
758 GLsizei width,
759 GLsizei height);
761 void BlitFramebufferHelper(GLint srcX0,
762 GLint srcY0,
763 GLint srcX1,
764 GLint srcY1,
765 GLint dstX0,
766 GLint dstY0,
767 GLint dstX1,
768 GLint dstY1,
769 GLbitfield mask,
770 GLenum filter);
772 private:
773 friend class ScopedFrameBufferBinder;
774 friend class ScopedResolvedFrameBufferBinder;
775 friend class BackFramebuffer;
777 // Initialize or re-initialize the shader translator.
778 bool InitializeShaderTranslator();
780 void UpdateCapabilities();
782 // Helpers for the glGen and glDelete functions.
783 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
784 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
785 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
786 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
787 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
788 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
789 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
790 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
791 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
792 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
793 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
794 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
795 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
796 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
797 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
798 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
800 // Helper for async upload token completion notification callback.
801 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
802 uint32 sync_data_shm_id,
803 uint32 sync_data_shm_offset);
807 // Workarounds
808 void OnFboChanged() const;
809 void OnUseFramebuffer() const;
811 error::ContextLostReason GetContextLostReasonFromResetStatus(
812 GLenum reset_status) const;
814 // TODO(gman): Cache these pointers?
815 BufferManager* buffer_manager() {
816 return group_->buffer_manager();
819 RenderbufferManager* renderbuffer_manager() {
820 return group_->renderbuffer_manager();
823 FramebufferManager* framebuffer_manager() {
824 return group_->framebuffer_manager();
827 ValuebufferManager* valuebuffer_manager() {
828 return group_->valuebuffer_manager();
831 PathManager* path_manager() { return group_->path_manager(); }
833 ProgramManager* program_manager() {
834 return group_->program_manager();
837 ShaderManager* shader_manager() {
838 return group_->shader_manager();
841 ShaderTranslatorCache* shader_translator_cache() {
842 return group_->shader_translator_cache();
845 const TextureManager* texture_manager() const {
846 return group_->texture_manager();
849 TextureManager* texture_manager() {
850 return group_->texture_manager();
853 MailboxManager* mailbox_manager() {
854 return group_->mailbox_manager();
857 ImageManager* image_manager() { return image_manager_.get(); }
859 VertexArrayManager* vertex_array_manager() {
860 return vertex_array_manager_.get();
863 MemoryTracker* memory_tracker() {
864 return group_->memory_tracker();
867 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
868 MemoryTracker* tracker = memory_tracker();
869 if (tracker) {
870 return tracker->EnsureGPUMemoryAvailable(estimated_size);
872 return true;
875 bool IsWebGLContext() const {
876 return webgl_version_ == 1 || webgl_version_ == 2;
879 bool IsOffscreenBufferMultisampled() const {
880 return offscreen_target_samples_ > 1;
883 // Creates a Texture for the given texture.
884 TextureRef* CreateTexture(
885 GLuint client_id, GLuint service_id) {
886 return texture_manager()->CreateTexture(client_id, service_id);
889 // Gets the texture info for the given texture. Returns NULL if none exists.
890 TextureRef* GetTexture(GLuint client_id) const {
891 return texture_manager()->GetTexture(client_id);
894 // Deletes the texture info for the given texture.
895 void RemoveTexture(GLuint client_id) {
896 texture_manager()->RemoveTexture(client_id);
899 // Get the size (in pixels) of the currently bound frame buffer (either FBO
900 // or regular back buffer).
901 gfx::Size GetBoundReadFrameBufferSize();
903 // Get the format of the currently bound frame buffer (either FBO or regular
904 // back buffer)
905 GLenum GetBoundReadFrameBufferTextureType();
906 GLenum GetBoundReadFrameBufferInternalFormat();
907 GLenum GetBoundDrawFrameBufferInternalFormat();
909 // Wrapper for CompressedTexImage2D commands.
910 error::Error DoCompressedTexImage2D(
911 GLenum target,
912 GLint level,
913 GLenum internal_format,
914 GLsizei width,
915 GLsizei height,
916 GLint border,
917 GLsizei image_size,
918 const void* data);
920 // Wrapper for CompressedTexImage3D commands.
921 error::Error DoCompressedTexImage3D(
922 GLenum target,
923 GLint level,
924 GLenum internal_format,
925 GLsizei width,
926 GLsizei height,
927 GLsizei depth,
928 GLint border,
929 GLsizei image_size,
930 const void* data);
932 // Wrapper for CompressedTexSubImage2D.
933 void DoCompressedTexSubImage2D(
934 GLenum target,
935 GLint level,
936 GLint xoffset,
937 GLint yoffset,
938 GLsizei width,
939 GLsizei height,
940 GLenum format,
941 GLsizei imageSize,
942 const void * data);
944 // Wrapper for CompressedTexSubImage3D.
945 void DoCompressedTexSubImage3D(
946 GLenum target,
947 GLint level,
948 GLint xoffset,
949 GLint yoffset,
950 GLint zoffset,
951 GLsizei width,
952 GLsizei height,
953 GLsizei depth,
954 GLenum format,
955 GLsizei image_size,
956 const void* data);
958 // Wrapper for CopyTexImage2D.
959 void DoCopyTexImage2D(
960 GLenum target,
961 GLint level,
962 GLenum internal_format,
963 GLint x,
964 GLint y,
965 GLsizei width,
966 GLsizei height,
967 GLint border);
969 // Wrapper for SwapBuffers.
970 void DoSwapBuffers();
972 // Wrapper for SwapInterval.
973 void DoSwapInterval(int interval);
975 // Wrapper for CopyTexSubImage2D.
976 void DoCopyTexSubImage2D(
977 GLenum target,
978 GLint level,
979 GLint xoffset,
980 GLint yoffset,
981 GLint x,
982 GLint y,
983 GLsizei width,
984 GLsizei height);
986 // Validation for TexSubImage2D.
987 bool ValidateTexSubImage2D(
988 error::Error* error,
989 const char* function_name,
990 GLenum target,
991 GLint level,
992 GLint xoffset,
993 GLint yoffset,
994 GLsizei width,
995 GLsizei height,
996 GLenum format,
997 GLenum type,
998 const void * data);
1000 // Wrapper for TexSubImage2D.
1001 error::Error DoTexSubImage2D(
1002 GLenum target,
1003 GLint level,
1004 GLint xoffset,
1005 GLint yoffset,
1006 GLsizei width,
1007 GLsizei height,
1008 GLenum format,
1009 GLenum type,
1010 const void * data);
1012 // Wrapper for TexSubImage3D.
1013 error::Error DoTexSubImage3D(
1014 GLenum target,
1015 GLint level,
1016 GLint xoffset,
1017 GLint yoffset,
1018 GLint zoffset,
1019 GLsizei width,
1020 GLsizei height,
1021 GLsizei depth,
1022 GLenum format,
1023 GLenum type,
1024 const void * data);
1026 // Extra validation for async tex(Sub)Image2D.
1027 bool ValidateAsyncTransfer(
1028 const char* function_name,
1029 TextureRef* texture_ref,
1030 GLenum target,
1031 GLint level,
1032 const void * data);
1034 // Wrapper for TexImageIOSurface2DCHROMIUM.
1035 void DoTexImageIOSurface2DCHROMIUM(
1036 GLenum target,
1037 GLsizei width,
1038 GLsizei height,
1039 GLuint io_surface_id,
1040 GLuint plane);
1042 void DoCopyTextureCHROMIUM(GLenum target,
1043 GLuint source_id,
1044 GLuint dest_id,
1045 GLenum internal_format,
1046 GLenum dest_type,
1047 GLboolean unpack_flip_y,
1048 GLboolean unpack_premultiply_alpha,
1049 GLboolean unpack_unmultiply_alpha);
1051 void DoCopySubTextureCHROMIUM(GLenum target,
1052 GLuint source_id,
1053 GLuint dest_id,
1054 GLint xoffset,
1055 GLint yoffset,
1056 GLint x,
1057 GLint y,
1058 GLsizei width,
1059 GLsizei height,
1060 GLboolean unpack_flip_y,
1061 GLboolean unpack_premultiply_alpha,
1062 GLboolean unpack_unmultiply_alpha);
1064 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1065 GLuint source_id,
1066 GLuint dest_id);
1068 // Wrapper for TexStorage2DEXT.
1069 void DoTexStorage2DEXT(
1070 GLenum target,
1071 GLint levels,
1072 GLenum internal_format,
1073 GLsizei width,
1074 GLsizei height);
1076 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1077 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1078 const GLbyte* key);
1079 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1080 GLenum target, const GLbyte* data);
1082 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1083 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1084 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1085 GLuint client_id);
1087 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1088 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1089 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1090 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1091 void DoUniformValueBufferCHROMIUM(GLint location,
1092 GLenum target,
1093 GLenum subscription);
1095 void DoBindTexImage2DCHROMIUM(
1096 GLenum target,
1097 GLint image_id);
1098 void DoReleaseTexImage2DCHROMIUM(
1099 GLenum target,
1100 GLint image_id);
1102 void DoTraceEndCHROMIUM(void);
1104 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1106 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1108 void DoFlushDriverCachesCHROMIUM(void);
1110 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1111 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1113 // Creates a Program for the given program.
1114 Program* CreateProgram(
1115 GLuint client_id, GLuint service_id) {
1116 return program_manager()->CreateProgram(client_id, service_id);
1119 // Gets the program info for the given program. Returns NULL if none exists.
1120 Program* GetProgram(GLuint client_id) {
1121 return program_manager()->GetProgram(client_id);
1124 #if defined(NDEBUG)
1125 void LogClientServiceMapping(
1126 const char* /* function_name */,
1127 GLuint /* client_id */,
1128 GLuint /* service_id */) {
1130 template<typename T>
1131 void LogClientServiceForInfo(
1132 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1134 #else
1135 void LogClientServiceMapping(
1136 const char* function_name, GLuint client_id, GLuint service_id) {
1137 if (service_logging_) {
1138 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1139 << ": client_id = " << client_id
1140 << ", service_id = " << service_id;
1143 template<typename T>
1144 void LogClientServiceForInfo(
1145 T* info, GLuint client_id, const char* function_name) {
1146 if (info) {
1147 LogClientServiceMapping(function_name, client_id, info->service_id());
1150 #endif
1152 // Gets the program info for the given program. If it's not a program
1153 // generates a GL error. Returns NULL if not program.
1154 Program* GetProgramInfoNotShader(
1155 GLuint client_id, const char* function_name) {
1156 Program* program = GetProgram(client_id);
1157 if (!program) {
1158 if (GetShader(client_id)) {
1159 LOCAL_SET_GL_ERROR(
1160 GL_INVALID_OPERATION, function_name, "shader passed for program");
1161 } else {
1162 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1165 LogClientServiceForInfo(program, client_id, function_name);
1166 return program;
1170 // Creates a Shader for the given shader.
1171 Shader* CreateShader(
1172 GLuint client_id,
1173 GLuint service_id,
1174 GLenum shader_type) {
1175 return shader_manager()->CreateShader(
1176 client_id, service_id, shader_type);
1179 // Gets the shader info for the given shader. Returns NULL if none exists.
1180 Shader* GetShader(GLuint client_id) {
1181 return shader_manager()->GetShader(client_id);
1184 // Gets the shader info for the given shader. If it's not a shader generates a
1185 // GL error. Returns NULL if not shader.
1186 Shader* GetShaderInfoNotProgram(
1187 GLuint client_id, const char* function_name) {
1188 Shader* shader = GetShader(client_id);
1189 if (!shader) {
1190 if (GetProgram(client_id)) {
1191 LOCAL_SET_GL_ERROR(
1192 GL_INVALID_OPERATION, function_name, "program passed for shader");
1193 } else {
1194 LOCAL_SET_GL_ERROR(
1195 GL_INVALID_VALUE, function_name, "unknown shader");
1198 LogClientServiceForInfo(shader, client_id, function_name);
1199 return shader;
1202 // Creates a buffer info for the given buffer.
1203 void CreateBuffer(GLuint client_id, GLuint service_id) {
1204 return buffer_manager()->CreateBuffer(client_id, service_id);
1207 // Gets the buffer info for the given buffer.
1208 Buffer* GetBuffer(GLuint client_id) {
1209 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1210 return buffer;
1213 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1214 // on glDeleteBuffers so we can make sure the user does not try to render
1215 // with deleted buffers.
1216 void RemoveBuffer(GLuint client_id);
1218 // Creates a framebuffer info for the given framebuffer.
1219 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1220 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1223 // Gets the framebuffer info for the given framebuffer.
1224 Framebuffer* GetFramebuffer(GLuint client_id) {
1225 return framebuffer_manager()->GetFramebuffer(client_id);
1228 // Removes the framebuffer info for the given framebuffer.
1229 void RemoveFramebuffer(GLuint client_id) {
1230 framebuffer_manager()->RemoveFramebuffer(client_id);
1233 // Creates a renderbuffer info for the given renderbuffer.
1234 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1235 return renderbuffer_manager()->CreateRenderbuffer(
1236 client_id, service_id);
1239 // Gets the renderbuffer info for the given renderbuffer.
1240 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1241 return renderbuffer_manager()->GetRenderbuffer(client_id);
1244 // Removes the renderbuffer info for the given renderbuffer.
1245 void RemoveRenderbuffer(GLuint client_id) {
1246 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1249 // Creates a valuebuffer info for the given valuebuffer.
1250 void CreateValuebuffer(GLuint client_id) {
1251 return valuebuffer_manager()->CreateValuebuffer(client_id);
1254 // Gets the valuebuffer info for a given valuebuffer.
1255 Valuebuffer* GetValuebuffer(GLuint client_id) {
1256 return valuebuffer_manager()->GetValuebuffer(client_id);
1259 // Removes the valuebuffer info for the given valuebuffer.
1260 void RemoveValuebuffer(GLuint client_id) {
1261 valuebuffer_manager()->RemoveValuebuffer(client_id);
1264 // Gets the vertex attrib manager for the given vertex array.
1265 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1266 VertexAttribManager* info =
1267 vertex_array_manager()->GetVertexAttribManager(client_id);
1268 return info;
1271 // Removes the vertex attrib manager for the given vertex array.
1272 void RemoveVertexAttribManager(GLuint client_id) {
1273 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1276 // Creates a vertex attrib manager for the given vertex array.
1277 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1278 GLuint client_id,
1279 GLuint service_id,
1280 bool client_visible) {
1281 return vertex_array_manager()->CreateVertexAttribManager(
1282 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1285 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1286 void DoBindUniformLocationCHROMIUM(
1287 GLuint client_id, GLint location, const char* name);
1289 error::Error GetAttribLocationHelper(
1290 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1291 const std::string& name_str);
1293 error::Error GetUniformLocationHelper(
1294 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1295 const std::string& name_str);
1297 error::Error GetFragDataLocationHelper(
1298 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1299 const std::string& name_str);
1301 // Wrapper for glShaderSource.
1302 void DoShaderSource(
1303 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1305 // Wrapper for glTransformFeedbackVaryings.
1306 void DoTransformFeedbackVaryings(
1307 GLuint client_program_id, GLsizei count, const char* const* varyings,
1308 GLenum buffer_mode);
1310 // Clear any textures used by the current program.
1311 bool ClearUnclearedTextures();
1313 // Clears any uncleared attachments attached to the given frame buffer.
1314 // Returns false if there was a generated GL error.
1315 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1317 // overridden from GLES2Decoder
1318 bool ClearLevel(Texture* texture,
1319 unsigned target,
1320 int level,
1321 unsigned format,
1322 unsigned type,
1323 int xoffset,
1324 int yoffset,
1325 int width,
1326 int height) override;
1328 // Restore all GL state that affects clearing.
1329 void RestoreClearState();
1331 // Remembers the state of some capabilities.
1332 // Returns: true if glEnable/glDisable should actually be called.
1333 bool SetCapabilityState(GLenum cap, bool enabled);
1335 // Check that the currently bound framebuffers are valid.
1336 // Generates GL error if not.
1337 bool CheckBoundFramebuffersValid(const char* func_name);
1339 // Check that the currently bound read framebuffer has a color image
1340 // attached. Generates GL error if not.
1341 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1343 // Check that the currently bound read framebuffer's color image
1344 // isn't the target texture of the glCopyTex{Sub}Image2D.
1345 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1347 // Check if a framebuffer meets our requirements.
1348 bool CheckFramebufferValid(
1349 Framebuffer* framebuffer,
1350 GLenum target,
1351 const char* func_name);
1353 // Check if the current valuebuffer exists and is valid. If not generates
1354 // the appropriate GL error. Returns true if the current valuebuffer is in
1355 // a usable state.
1356 bool CheckCurrentValuebuffer(const char* function_name);
1358 // Check if the current valuebuffer exists and is valiud and that the
1359 // value buffer is actually subscribed to the given subscription
1360 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1361 const char* function_name);
1363 // Check if the location can be used for the given subscription target. If not
1364 // generates the appropriate GL error. Returns true if the location is usable
1365 bool CheckSubscriptionTarget(GLint location,
1366 GLenum subscription,
1367 const char* function_name);
1369 // Checks if the current program exists and is valid. If not generates the
1370 // appropriate GL error. Returns true if the current program is in a usable
1371 // state.
1372 bool CheckCurrentProgram(const char* function_name);
1374 // Checks if the current program exists and is valid and that location is not
1375 // -1. If the current program is not valid generates the appropriate GL
1376 // error. Returns true if the current program is in a usable state and
1377 // location is not -1.
1378 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1380 // Checks if the current program samples a texture that is also the color
1381 // image of the current bound framebuffer, i.e., the source and destination
1382 // of the draw operation are the same.
1383 bool CheckDrawingFeedbackLoops();
1385 // Checks if |api_type| is valid for the given uniform
1386 // If the api type is not valid generates the appropriate GL
1387 // error. Returns true if |api_type| is valid for the uniform
1388 bool CheckUniformForApiType(const Program::UniformInfo* info,
1389 const char* function_name,
1390 Program::UniformApiType api_type);
1392 // Gets the type of a uniform for a location in the current program. Sets GL
1393 // errors if the current program is not valid. Returns true if the current
1394 // program is valid and the location exists. Adjusts count so it
1395 // does not overflow the uniform.
1396 bool PrepForSetUniformByLocation(GLint fake_location,
1397 const char* function_name,
1398 Program::UniformApiType api_type,
1399 GLint* real_location,
1400 GLenum* type,
1401 GLsizei* count);
1403 // Gets the service id for any simulated backbuffer fbo.
1404 GLuint GetBackbufferServiceId() const;
1406 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1407 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1409 // Helper for glGetVertexAttrib
1410 void GetVertexAttribHelper(
1411 const VertexAttrib* attrib, GLenum pname, GLint* param);
1413 // Wrapper for glActiveTexture
1414 void DoActiveTexture(GLenum texture_unit);
1416 // Wrapper for glAttachShader
1417 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1419 // Wrapper for glBindBuffer since we need to track the current targets.
1420 void DoBindBuffer(GLenum target, GLuint buffer);
1422 // Wrapper for glBindFramebuffer since we need to track the current targets.
1423 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1425 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1426 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1428 // Wrapper for glBindTexture since we need to track the current targets.
1429 void DoBindTexture(GLenum target, GLuint texture);
1431 // Wrapper for glBindVertexArrayOES
1432 void DoBindVertexArrayOES(GLuint array);
1433 void EmulateVertexArrayState();
1435 // Wrapper for glBlitFramebufferCHROMIUM.
1436 void DoBlitFramebufferCHROMIUM(
1437 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1438 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1439 GLbitfield mask, GLenum filter);
1441 // Wrapper for glBufferSubData.
1442 void DoBufferSubData(
1443 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1445 // Wrapper for glCheckFramebufferStatus
1446 GLenum DoCheckFramebufferStatus(GLenum target);
1448 // Wrapper for glClear
1449 error::Error DoClear(GLbitfield mask);
1451 // Wrappers for various state.
1452 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1453 void DoSampleCoverage(GLclampf value, GLboolean invert);
1455 // Wrapper for glCompileShader.
1456 void DoCompileShader(GLuint shader);
1458 // Wrapper for glDetachShader
1459 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1461 // Wrapper for glDisable
1462 void DoDisable(GLenum cap);
1464 // Wrapper for glDisableVertexAttribArray.
1465 void DoDisableVertexAttribArray(GLuint index);
1467 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1468 // attachments.
1469 void DoDiscardFramebufferEXT(GLenum target,
1470 GLsizei numAttachments,
1471 const GLenum* attachments);
1473 // Wrapper for glEnable
1474 void DoEnable(GLenum cap);
1476 // Wrapper for glEnableVertexAttribArray.
1477 void DoEnableVertexAttribArray(GLuint index);
1479 // Wrapper for glFinish.
1480 void DoFinish();
1482 // Wrapper for glFlush.
1483 void DoFlush();
1485 // Wrapper for glFramebufferRenderbufffer.
1486 void DoFramebufferRenderbuffer(
1487 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1488 GLuint renderbuffer);
1490 // Wrapper for glFramebufferTexture2D.
1491 void DoFramebufferTexture2D(
1492 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1493 GLint level);
1495 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1496 void DoFramebufferTexture2DMultisample(
1497 GLenum target, GLenum attachment, GLenum textarget,
1498 GLuint texture, GLint level, GLsizei samples);
1500 // Common implementation for both DoFramebufferTexture2D wrappers.
1501 void DoFramebufferTexture2DCommon(const char* name,
1502 GLenum target, GLenum attachment, GLenum textarget,
1503 GLuint texture, GLint level, GLsizei samples);
1505 // Wrapper for glFramebufferTextureLayer.
1506 void DoFramebufferTextureLayer(
1507 GLenum target, GLenum attachment, GLuint texture, GLint level,
1508 GLint layer);
1510 // Wrapper for glGenerateMipmap
1511 void DoGenerateMipmap(GLenum target);
1513 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1514 // to account for different pname values defined in different extension
1515 // variants.
1516 GLenum AdjustGetPname(GLenum pname);
1518 // Wrapper for DoGetBooleanv.
1519 void DoGetBooleanv(GLenum pname, GLboolean* params);
1521 // Wrapper for DoGetFloatv.
1522 void DoGetFloatv(GLenum pname, GLfloat* params);
1524 // Wrapper for glGetFramebufferAttachmentParameteriv.
1525 void DoGetFramebufferAttachmentParameteriv(
1526 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1528 // Wrapper for glGetInteger64v.
1529 void DoGetInteger64v(GLenum pname, GLint64* params);
1531 // Wrapper for glGetIntegerv.
1532 void DoGetIntegerv(GLenum pname, GLint* params);
1534 // Gets the max value in a range in a buffer.
1535 GLuint DoGetMaxValueInBufferCHROMIUM(
1536 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1538 // Wrapper for glGetBufferParameteri64v.
1539 void DoGetBufferParameteri64v(
1540 GLenum target, GLenum pname, GLint64* params);
1542 // Wrapper for glGetBufferParameteriv.
1543 void DoGetBufferParameteriv(
1544 GLenum target, GLenum pname, GLint* params);
1546 // Wrapper for glGetProgramiv.
1547 void DoGetProgramiv(
1548 GLuint program_id, GLenum pname, GLint* params);
1550 // Wrapper for glRenderbufferParameteriv.
1551 void DoGetRenderbufferParameteriv(
1552 GLenum target, GLenum pname, GLint* params);
1554 // Wrapper for glGetShaderiv
1555 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1557 // Wrappers for glGetTexParameter.
1558 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1559 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1560 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1562 // Wrappers for glGetVertexAttrib.
1563 template <typename T>
1564 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1565 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1566 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1567 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1568 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1570 // Wrappers for glIsXXX functions.
1571 bool DoIsEnabled(GLenum cap);
1572 bool DoIsBuffer(GLuint client_id);
1573 bool DoIsFramebuffer(GLuint client_id);
1574 bool DoIsProgram(GLuint client_id);
1575 bool DoIsRenderbuffer(GLuint client_id);
1576 bool DoIsShader(GLuint client_id);
1577 bool DoIsTexture(GLuint client_id);
1578 bool DoIsVertexArrayOES(GLuint client_id);
1579 bool DoIsPathCHROMIUM(GLuint client_id);
1581 // Wrapper for glLinkProgram
1582 void DoLinkProgram(GLuint program);
1584 // Wrapper for glReadBuffer
1585 void DoReadBuffer(GLenum src);
1587 // Wrapper for glRenderbufferStorage.
1588 void DoRenderbufferStorage(
1589 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1591 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1592 void DoRenderbufferStorageMultisampleCHROMIUM(
1593 GLenum target, GLsizei samples, GLenum internalformat,
1594 GLsizei width, GLsizei height);
1596 // Handler for glRenderbufferStorageMultisampleEXT
1597 // (multisampled_render_to_texture).
1598 void DoRenderbufferStorageMultisampleEXT(
1599 GLenum target, GLsizei samples, GLenum internalformat,
1600 GLsizei width, GLsizei height);
1602 // Common validation for multisample extensions.
1603 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1604 GLenum internalformat,
1605 GLsizei width,
1606 GLsizei height);
1608 // Verifies that the currently bound multisample renderbuffer is valid
1609 // Very slow! Only done on platforms with driver bugs that return invalid
1610 // buffers under memory pressure
1611 bool VerifyMultisampleRenderbufferIntegrity(
1612 GLuint renderbuffer, GLenum format);
1614 // Wrapper for glReleaseShaderCompiler.
1615 void DoReleaseShaderCompiler() { }
1617 // Wrappers for glSamplerParameter*v functions.
1618 void DoSamplerParameterfv(
1619 GLuint sampler, GLenum pname, const GLfloat* params);
1620 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1622 // Wrappers for glTexParameter functions.
1623 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1624 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1625 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1626 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1628 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1629 // spec only these 2 functions can be used to set sampler uniforms.
1630 void DoUniform1i(GLint fake_location, GLint v0);
1631 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1632 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1633 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1634 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1636 // Wrappers for glUniformfv because some drivers don't correctly accept
1637 // bool uniforms.
1638 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1639 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1640 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1641 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1643 void DoUniformMatrix2fv(
1644 GLint fake_location, GLsizei count, GLboolean transpose,
1645 const GLfloat* value);
1646 void DoUniformMatrix3fv(
1647 GLint fake_location, GLsizei count, GLboolean transpose,
1648 const GLfloat* value);
1649 void DoUniformMatrix4fv(
1650 GLint fake_location, GLsizei count, GLboolean transpose,
1651 const GLfloat* value);
1653 template <typename T>
1654 bool SetVertexAttribValue(
1655 const char* function_name, GLuint index, const T* value);
1657 // Wrappers for glVertexAttrib??
1658 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1659 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1660 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1661 void DoVertexAttrib4f(
1662 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1663 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1664 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1665 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1666 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1667 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1668 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1669 void DoVertexAttribI4ui(
1670 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1671 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1673 // Wrapper for glViewport
1674 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1676 // Wrapper for glUseProgram
1677 void DoUseProgram(GLuint program);
1679 // Wrapper for glValidateProgram.
1680 void DoValidateProgram(GLuint program_client_id);
1682 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1683 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1684 void DoPopGroupMarkerEXT(void);
1686 // Gets the number of values that will be returned by glGetXXX. Returns
1687 // false if pname is unknown.
1688 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1690 // Checks if the current program and vertex attributes are valid for drawing.
1691 bool IsDrawValid(
1692 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1693 GLsizei primcount);
1695 // Returns true if successful, simulated will be true if attrib0 was
1696 // simulated.
1697 bool SimulateAttrib0(
1698 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1699 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1701 // If an image is bound to texture, this will call Will/DidUseTexImage
1702 // if needed.
1703 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1704 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1706 // Returns false if textures were replaced.
1707 bool PrepareTexturesForRender();
1708 void RestoreStateForTextures();
1710 // Returns true if GL_FIXED attribs were simulated.
1711 bool SimulateFixedAttribs(
1712 const char* function_name,
1713 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1714 void RestoreStateForSimulatedFixedAttribs();
1716 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1717 // cases (primcount is always 1 for non-instanced).
1718 error::Error DoDrawArrays(
1719 const char* function_name,
1720 bool instanced, GLenum mode, GLint first, GLsizei count,
1721 GLsizei primcount);
1722 error::Error DoDrawElements(
1723 const char* function_name,
1724 bool instanced, GLenum mode, GLsizei count, GLenum type,
1725 int32 offset, GLsizei primcount);
1727 GLenum GetBindTargetForSamplerType(GLenum type) {
1728 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1729 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1730 switch (type) {
1731 case GL_SAMPLER_2D:
1732 return GL_TEXTURE_2D;
1733 case GL_SAMPLER_CUBE:
1734 return GL_TEXTURE_CUBE_MAP;
1735 case GL_SAMPLER_EXTERNAL_OES:
1736 return GL_TEXTURE_EXTERNAL_OES;
1737 case GL_SAMPLER_2D_RECT_ARB:
1738 return GL_TEXTURE_RECTANGLE_ARB;
1741 NOTREACHED();
1742 return 0;
1745 // Gets the framebuffer info for a particular target.
1746 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1747 Framebuffer* framebuffer = NULL;
1748 switch (target) {
1749 case GL_FRAMEBUFFER:
1750 case GL_DRAW_FRAMEBUFFER_EXT:
1751 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1752 break;
1753 case GL_READ_FRAMEBUFFER_EXT:
1754 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1755 break;
1756 default:
1757 NOTREACHED();
1758 break;
1760 return framebuffer;
1763 Renderbuffer* GetRenderbufferInfoForTarget(
1764 GLenum target) {
1765 Renderbuffer* renderbuffer = NULL;
1766 switch (target) {
1767 case GL_RENDERBUFFER:
1768 renderbuffer = state_.bound_renderbuffer.get();
1769 break;
1770 default:
1771 NOTREACHED();
1772 break;
1774 return renderbuffer;
1777 // Validates the program and location for a glGetUniform call and returns
1778 // a SizeResult setup to receive the result. Returns true if glGetUniform
1779 // should be called.
1780 template <class T>
1781 bool GetUniformSetup(GLuint program,
1782 GLint fake_location,
1783 uint32 shm_id,
1784 uint32 shm_offset,
1785 error::Error* error,
1786 GLint* real_location,
1787 GLuint* service_id,
1788 SizedResult<T>** result,
1789 GLenum* result_type,
1790 GLsizei* result_size);
1792 bool WasContextLost() const override;
1793 bool WasContextLostByRobustnessExtension() const override;
1794 void MarkContextLost(error::ContextLostReason reason) override;
1795 bool CheckResetStatus();
1797 #if defined(OS_MACOSX)
1798 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1799 #endif
1801 bool GetCompressedTexSizeInBytes(
1802 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1803 GLenum format, GLsizei* size_in_bytes);
1805 bool ValidateCompressedTexDimensions(
1806 const char* function_name, GLenum target, GLint level,
1807 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1808 bool ValidateCompressedTexFuncData(
1809 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1810 GLenum format, GLsizei size);
1811 bool ValidateCompressedTexSubDimensions(
1812 const char* function_name,
1813 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1814 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1815 Texture* texture);
1816 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1817 GLenum target,
1818 TextureRef* source_texture_ref,
1819 TextureRef* dest_texture_ref,
1820 GLenum dest_internal_format);
1821 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1822 GLenum target,
1823 TextureRef* source_texture_ref,
1824 TextureRef* dest_texture_ref);
1826 void RenderWarning(const char* filename, int line, const std::string& msg);
1827 void PerformanceWarning(
1828 const char* filename, int line, const std::string& msg);
1830 const FeatureInfo::FeatureFlags& features() const {
1831 return feature_info_->feature_flags();
1834 const FeatureInfo::Workarounds& workarounds() const {
1835 return feature_info_->workarounds();
1838 bool ShouldDeferDraws() {
1839 return !offscreen_target_frame_buffer_.get() &&
1840 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1841 surface_->DeferDraws();
1844 bool ShouldDeferReads() {
1845 return !offscreen_target_frame_buffer_.get() &&
1846 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1847 surface_->DeferDraws();
1850 bool IsRobustnessSupported() {
1851 return has_robustness_extension_ &&
1852 context_->WasAllocatedUsingRobustnessExtension();
1855 error::Error WillAccessBoundFramebufferForDraw() {
1856 if (ShouldDeferDraws())
1857 return error::kDeferCommandUntilLater;
1858 if (!offscreen_target_frame_buffer_.get() &&
1859 !framebuffer_state_.bound_draw_framebuffer.get() &&
1860 !surface_->SetBackbufferAllocation(true))
1861 return error::kLostContext;
1862 return error::kNoError;
1865 error::Error WillAccessBoundFramebufferForRead() {
1866 if (ShouldDeferReads())
1867 return error::kDeferCommandUntilLater;
1868 if (!offscreen_target_frame_buffer_.get() &&
1869 !framebuffer_state_.bound_read_framebuffer.get() &&
1870 !surface_->SetBackbufferAllocation(true))
1871 return error::kLostContext;
1872 return error::kNoError;
1875 // Set remaining commands to process to 0 to force DoCommands to return
1876 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1877 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1879 void ProcessPendingReadPixels(bool did_finish);
1880 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1882 // Generate a member function prototype for each command in an automated and
1883 // typesafe way.
1884 #define GLES2_CMD_OP(name) \
1885 Error Handle##name(uint32 immediate_data_size, const void* data);
1887 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1889 #undef GLES2_CMD_OP
1891 // The GL context this decoder renders to on behalf of the client.
1892 scoped_refptr<gfx::GLSurface> surface_;
1893 scoped_refptr<gfx::GLContext> context_;
1895 // The ContextGroup for this decoder uses to track resources.
1896 scoped_refptr<ContextGroup> group_;
1898 DebugMarkerManager debug_marker_manager_;
1899 Logger logger_;
1901 // All the state for this context.
1902 ContextState state_;
1904 // Current width and height of the offscreen frame buffer.
1905 gfx::Size offscreen_size_;
1907 // Util to help with GL.
1908 GLES2Util util_;
1910 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1911 GLuint attrib_0_buffer_id_;
1913 // The value currently in attrib_0.
1914 Vec4 attrib_0_value_;
1916 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1917 bool attrib_0_buffer_matches_value_;
1919 // The size of attrib 0.
1920 GLsizei attrib_0_size_;
1922 // The buffer used to simulate GL_FIXED attribs.
1923 GLuint fixed_attrib_buffer_id_;
1925 // The size of fiixed attrib buffer.
1926 GLsizei fixed_attrib_buffer_size_;
1928 // The offscreen frame buffer that the client renders to. With EGL, the
1929 // depth and stencil buffers are separate. With regular GL there is a single
1930 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1931 // offscreen_target_stencil_render_buffer_ is unused.
1932 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1933 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1934 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1935 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1936 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1937 GLenum offscreen_target_color_format_;
1938 GLenum offscreen_target_depth_format_;
1939 GLenum offscreen_target_stencil_format_;
1940 GLsizei offscreen_target_samples_;
1941 GLboolean offscreen_target_buffer_preserved_;
1943 // The copy that is saved when SwapBuffers is called.
1944 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1945 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1946 scoped_refptr<TextureRef>
1947 offscreen_saved_color_texture_info_;
1949 // The copy that is used as the destination for multi-sample resolves.
1950 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1951 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1952 GLenum offscreen_saved_color_format_;
1954 scoped_ptr<QueryManager> query_manager_;
1956 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1958 scoped_ptr<ImageManager> image_manager_;
1960 base::Callback<void(gfx::Size, float)> resize_callback_;
1962 WaitSyncPointCallback wait_sync_point_callback_;
1964 ShaderCacheCallback shader_cache_callback_;
1966 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1968 // The format of the back buffer_
1969 GLenum back_buffer_color_format_;
1970 bool back_buffer_has_depth_;
1971 bool back_buffer_has_stencil_;
1972 // This tracks read buffer for both offscreen/onscreen backbuffer cases.
1973 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1974 // setting is set correctly when SwapBuffers().
1975 GLenum back_buffer_read_buffer_;
1977 bool surfaceless_;
1979 // Backbuffer attachments that are currently undefined.
1980 uint32 backbuffer_needs_clear_bits_;
1982 // The current decoder error communicates the decoder error through command
1983 // processing functions that do not return the error value. Should be set only
1984 // if not returning an error.
1985 error::Error current_decoder_error_;
1987 bool use_shader_translator_;
1988 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1989 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1991 DisallowedFeatures disallowed_features_;
1993 // Cached from ContextGroup
1994 const Validators* validators_;
1995 scoped_refptr<FeatureInfo> feature_info_;
1997 int frame_number_;
1999 // Number of commands remaining to be processed in DoCommands().
2000 int commands_to_process_;
2002 bool has_robustness_extension_;
2003 error::ContextLostReason context_lost_reason_;
2004 bool context_was_lost_;
2005 bool reset_by_robustness_extension_;
2006 bool supports_post_sub_buffer_;
2008 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2009 // 0: other types
2010 // 1: WebGL 1
2011 // 2: WebGL 2
2012 unsigned webgl_version_;
2014 // These flags are used to override the state of the shared feature_info_
2015 // member. Because the same FeatureInfo instance may be shared among many
2016 // contexts, the assumptions on the availablity of extensions in WebGL
2017 // contexts may be broken. These flags override the shared state to preserve
2018 // WebGL semantics.
2019 bool derivatives_explicitly_enabled_;
2020 bool frag_depth_explicitly_enabled_;
2021 bool draw_buffers_explicitly_enabled_;
2022 bool shader_texture_lod_explicitly_enabled_;
2024 bool compile_shader_always_succeeds_;
2026 // An optional behaviour to lose the context and group when OOM.
2027 bool lose_context_when_out_of_memory_;
2029 // Log extra info.
2030 bool service_logging_;
2032 #if defined(OS_MACOSX)
2033 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2034 TextureToIOSurfaceMap texture_to_io_surface_map_;
2035 #endif
2037 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2038 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2040 // Cached values of the currently assigned viewport dimensions.
2041 GLsizei viewport_max_width_;
2042 GLsizei viewport_max_height_;
2044 // Command buffer stats.
2045 base::TimeDelta total_processing_commands_time_;
2047 // States related to each manager.
2048 DecoderTextureState texture_state_;
2049 DecoderFramebufferState framebuffer_state_;
2051 scoped_ptr<GPUTracer> gpu_tracer_;
2052 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2053 const unsigned char* cb_command_trace_category_;
2054 const unsigned char* gpu_decoder_category_;
2055 int gpu_trace_level_;
2056 bool gpu_trace_commands_;
2057 bool gpu_debug_commands_;
2059 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2061 // Used to validate multisample renderbuffers if needed
2062 GLuint validation_texture_;
2063 GLuint validation_fbo_multisample_;
2064 GLuint validation_fbo_;
2066 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2067 uint32 immediate_data_size,
2068 const void* data);
2070 // A struct to hold info about each command.
2071 struct CommandInfo {
2072 CmdHandler cmd_handler;
2073 uint8 arg_flags; // How to handle the arguments for this command
2074 uint8 cmd_flags; // How to handle this command
2075 uint16 arg_count; // How many arguments are expected for this command.
2078 // A table of CommandInfo for all the commands.
2079 static const CommandInfo command_info[kNumCommands - kStartPoint];
2081 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2084 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2085 #define GLES2_CMD_OP(name) \
2087 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2088 cmds::name::cmd_flags, \
2089 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2091 , /* NOLINT */
2092 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2093 #undef GLES2_CMD_OP
2096 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2097 const char* function_name, ErrorState* error_state)
2098 : function_name_(function_name),
2099 error_state_(error_state) {
2100 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2103 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2104 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2107 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2108 TextureUnit& info = state->texture_units[0];
2109 GLuint last_id;
2110 scoped_refptr<TextureRef> texture_ref;
2111 switch (target) {
2112 case GL_TEXTURE_2D:
2113 texture_ref = info.bound_texture_2d;
2114 break;
2115 case GL_TEXTURE_CUBE_MAP:
2116 texture_ref = info.bound_texture_cube_map;
2117 break;
2118 case GL_TEXTURE_EXTERNAL_OES:
2119 texture_ref = info.bound_texture_external_oes;
2120 break;
2121 case GL_TEXTURE_RECTANGLE_ARB:
2122 texture_ref = info.bound_texture_rectangle_arb;
2123 break;
2124 default:
2125 NOTREACHED();
2126 break;
2128 if (texture_ref.get()) {
2129 last_id = texture_ref->service_id();
2130 } else {
2131 last_id = 0;
2134 glBindTexture(target, last_id);
2135 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2138 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2139 GLuint id,
2140 GLenum target)
2141 : state_(state),
2142 target_(target) {
2143 ScopedGLErrorSuppressor suppressor(
2144 "ScopedTextureBinder::ctor", state_->GetErrorState());
2146 // TODO(apatrick): Check if there are any other states that need to be reset
2147 // before binding a new texture.
2148 glActiveTexture(GL_TEXTURE0);
2149 glBindTexture(target, id);
2152 ScopedTextureBinder::~ScopedTextureBinder() {
2153 ScopedGLErrorSuppressor suppressor(
2154 "ScopedTextureBinder::dtor", state_->GetErrorState());
2155 RestoreCurrentTextureBindings(state_, target_);
2158 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2159 GLuint id)
2160 : state_(state) {
2161 ScopedGLErrorSuppressor suppressor(
2162 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2163 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2166 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2167 ScopedGLErrorSuppressor suppressor(
2168 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2169 state_->RestoreRenderbufferBindings();
2172 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2173 GLuint id)
2174 : decoder_(decoder) {
2175 ScopedGLErrorSuppressor suppressor(
2176 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2177 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2178 decoder->OnFboChanged();
2181 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2182 ScopedGLErrorSuppressor suppressor(
2183 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2184 decoder_->RestoreCurrentFramebufferBindings();
2187 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2188 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2189 : decoder_(decoder) {
2190 resolve_and_bind_ = (
2191 decoder_->offscreen_target_frame_buffer_.get() &&
2192 decoder_->IsOffscreenBufferMultisampled() &&
2193 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2194 enforce_internal_framebuffer));
2195 if (!resolve_and_bind_)
2196 return;
2198 ScopedGLErrorSuppressor suppressor(
2199 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2200 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2201 decoder_->offscreen_target_frame_buffer_->id());
2202 GLuint targetid;
2203 if (internal) {
2204 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2205 decoder_->offscreen_resolved_frame_buffer_.reset(
2206 new BackFramebuffer(decoder_));
2207 decoder_->offscreen_resolved_frame_buffer_->Create();
2208 decoder_->offscreen_resolved_color_texture_.reset(
2209 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2210 decoder_->offscreen_resolved_color_texture_->Create();
2212 DCHECK(decoder_->offscreen_saved_color_format_);
2213 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2214 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2215 false);
2216 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2217 decoder_->offscreen_resolved_color_texture_.get());
2218 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2219 GL_FRAMEBUFFER_COMPLETE) {
2220 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2221 << "because offscreen resolved FBO was incomplete.";
2222 return;
2225 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2226 } else {
2227 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2229 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2230 const int width = decoder_->offscreen_size_.width();
2231 const int height = decoder_->offscreen_size_.height();
2232 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2233 decoder->BlitFramebufferHelper(0,
2235 width,
2236 height,
2239 width,
2240 height,
2241 GL_COLOR_BUFFER_BIT,
2242 GL_NEAREST);
2243 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2246 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2247 if (!resolve_and_bind_)
2248 return;
2250 ScopedGLErrorSuppressor suppressor(
2251 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2252 decoder_->RestoreCurrentFramebufferBindings();
2253 if (decoder_->state_.enable_flags.scissor_test) {
2254 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2258 BackTexture::BackTexture(
2259 MemoryTracker* memory_tracker,
2260 ContextState* state)
2261 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2262 state_(state),
2263 bytes_allocated_(0),
2264 id_(0) {
2267 BackTexture::~BackTexture() {
2268 // This does not destroy the render texture because that would require that
2269 // the associated GL context was current. Just check that it was explicitly
2270 // destroyed.
2271 DCHECK_EQ(id_, 0u);
2274 void BackTexture::Create() {
2275 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2276 state_->GetErrorState());
2277 Destroy();
2278 glGenTextures(1, &id_);
2279 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2285 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2286 // never called on an offscreen context, no data will ever be uploaded to the
2287 // saved offscreen color texture (it is deferred until to when SwapBuffers
2288 // is called). My idea is that some nvidia drivers might have a bug where
2289 // deleting a texture that has never been populated might cause a
2290 // crash.
2291 glTexImage2D(
2292 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2294 bytes_allocated_ = 16u * 16u * 4u;
2295 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2298 bool BackTexture::AllocateStorage(
2299 const gfx::Size& size, GLenum format, bool zero) {
2300 DCHECK_NE(id_, 0u);
2301 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2302 state_->GetErrorState());
2303 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2304 uint32 image_size = 0;
2305 GLES2Util::ComputeImageDataSizes(
2306 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2307 NULL, NULL);
2309 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2310 return false;
2313 scoped_ptr<char[]> zero_data;
2314 if (zero) {
2315 zero_data.reset(new char[image_size]);
2316 memset(zero_data.get(), 0, image_size);
2319 glTexImage2D(GL_TEXTURE_2D,
2320 0, // mip level
2321 format,
2322 size.width(),
2323 size.height(),
2324 0, // border
2325 format,
2326 GL_UNSIGNED_BYTE,
2327 zero_data.get());
2329 size_ = size;
2331 bool success = glGetError() == GL_NO_ERROR;
2332 if (success) {
2333 memory_tracker_.TrackMemFree(bytes_allocated_);
2334 bytes_allocated_ = image_size;
2335 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2337 return success;
2340 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2341 DCHECK_NE(id_, 0u);
2342 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2343 state_->GetErrorState());
2344 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2345 glCopyTexImage2D(GL_TEXTURE_2D,
2346 0, // level
2347 format,
2348 0, 0,
2349 size.width(),
2350 size.height(),
2351 0); // border
2354 void BackTexture::Destroy() {
2355 if (id_ != 0) {
2356 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2357 state_->GetErrorState());
2358 glDeleteTextures(1, &id_);
2359 id_ = 0;
2361 memory_tracker_.TrackMemFree(bytes_allocated_);
2362 bytes_allocated_ = 0;
2365 void BackTexture::Invalidate() {
2366 id_ = 0;
2369 BackRenderbuffer::BackRenderbuffer(
2370 RenderbufferManager* renderbuffer_manager,
2371 MemoryTracker* memory_tracker,
2372 ContextState* state)
2373 : renderbuffer_manager_(renderbuffer_manager),
2374 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2375 state_(state),
2376 bytes_allocated_(0),
2377 id_(0) {
2380 BackRenderbuffer::~BackRenderbuffer() {
2381 // This does not destroy the render buffer because that would require that
2382 // the associated GL context was current. Just check that it was explicitly
2383 // destroyed.
2384 DCHECK_EQ(id_, 0u);
2387 void BackRenderbuffer::Create() {
2388 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2389 state_->GetErrorState());
2390 Destroy();
2391 glGenRenderbuffersEXT(1, &id_);
2394 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2395 const gfx::Size& size,
2396 GLenum format,
2397 GLsizei samples) {
2398 ScopedGLErrorSuppressor suppressor(
2399 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2400 ScopedRenderBufferBinder binder(state_, id_);
2402 uint32 estimated_size = 0;
2403 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2404 size.width(), size.height(), samples, format, &estimated_size)) {
2405 return false;
2408 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2409 return false;
2412 if (samples <= 1) {
2413 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2414 format,
2415 size.width(),
2416 size.height());
2417 } else {
2418 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2419 GL_RENDERBUFFER,
2420 samples,
2421 format,
2422 size.width(),
2423 size.height());
2425 bool success = glGetError() == GL_NO_ERROR;
2426 if (success) {
2427 // Mark the previously allocated bytes as free.
2428 memory_tracker_.TrackMemFree(bytes_allocated_);
2429 bytes_allocated_ = estimated_size;
2430 // Track the newly allocated bytes.
2431 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2433 return success;
2436 void BackRenderbuffer::Destroy() {
2437 if (id_ != 0) {
2438 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2439 state_->GetErrorState());
2440 glDeleteRenderbuffersEXT(1, &id_);
2441 id_ = 0;
2443 memory_tracker_.TrackMemFree(bytes_allocated_);
2444 bytes_allocated_ = 0;
2447 void BackRenderbuffer::Invalidate() {
2448 id_ = 0;
2451 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2452 : decoder_(decoder),
2453 id_(0) {
2456 BackFramebuffer::~BackFramebuffer() {
2457 // This does not destroy the frame buffer because that would require that
2458 // the associated GL context was current. Just check that it was explicitly
2459 // destroyed.
2460 DCHECK_EQ(id_, 0u);
2463 void BackFramebuffer::Create() {
2464 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2465 decoder_->GetErrorState());
2466 Destroy();
2467 glGenFramebuffersEXT(1, &id_);
2470 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2471 DCHECK_NE(id_, 0u);
2472 ScopedGLErrorSuppressor suppressor(
2473 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2474 ScopedFrameBufferBinder binder(decoder_, id_);
2475 GLuint attach_id = texture ? texture->id() : 0;
2476 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2477 GL_COLOR_ATTACHMENT0,
2478 GL_TEXTURE_2D,
2479 attach_id,
2483 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2484 BackRenderbuffer* render_buffer) {
2485 DCHECK_NE(id_, 0u);
2486 ScopedGLErrorSuppressor suppressor(
2487 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2488 ScopedFrameBufferBinder binder(decoder_, id_);
2489 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2490 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2491 target,
2492 GL_RENDERBUFFER,
2493 attach_id);
2496 void BackFramebuffer::Destroy() {
2497 if (id_ != 0) {
2498 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2499 decoder_->GetErrorState());
2500 glDeleteFramebuffersEXT(1, &id_);
2501 id_ = 0;
2505 void BackFramebuffer::Invalidate() {
2506 id_ = 0;
2509 GLenum BackFramebuffer::CheckStatus() {
2510 DCHECK_NE(id_, 0u);
2511 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2512 decoder_->GetErrorState());
2513 ScopedFrameBufferBinder binder(decoder_, id_);
2514 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2517 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2518 return new GLES2DecoderImpl(group);
2521 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2522 : GLES2Decoder(),
2523 group_(group),
2524 logger_(&debug_marker_manager_),
2525 state_(group_->feature_info(), this, &logger_),
2526 attrib_0_buffer_id_(0),
2527 attrib_0_buffer_matches_value_(true),
2528 attrib_0_size_(0),
2529 fixed_attrib_buffer_id_(0),
2530 fixed_attrib_buffer_size_(0),
2531 offscreen_target_color_format_(0),
2532 offscreen_target_depth_format_(0),
2533 offscreen_target_stencil_format_(0),
2534 offscreen_target_samples_(0),
2535 offscreen_target_buffer_preserved_(true),
2536 offscreen_saved_color_format_(0),
2537 back_buffer_color_format_(0),
2538 back_buffer_has_depth_(false),
2539 back_buffer_has_stencil_(false),
2540 back_buffer_read_buffer_(GL_BACK),
2541 surfaceless_(false),
2542 backbuffer_needs_clear_bits_(0),
2543 current_decoder_error_(error::kNoError),
2544 use_shader_translator_(true),
2545 validators_(group_->feature_info()->validators()),
2546 feature_info_(group_->feature_info()),
2547 frame_number_(0),
2548 has_robustness_extension_(false),
2549 context_lost_reason_(error::kUnknown),
2550 context_was_lost_(false),
2551 reset_by_robustness_extension_(false),
2552 supports_post_sub_buffer_(false),
2553 webgl_version_(0),
2554 derivatives_explicitly_enabled_(false),
2555 frag_depth_explicitly_enabled_(false),
2556 draw_buffers_explicitly_enabled_(false),
2557 shader_texture_lod_explicitly_enabled_(false),
2558 compile_shader_always_succeeds_(false),
2559 lose_context_when_out_of_memory_(false),
2560 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2561 switches::kEnableGPUServiceLoggingGPU)),
2562 viewport_max_width_(0),
2563 viewport_max_height_(0),
2564 texture_state_(group_->feature_info()
2565 ->workarounds()
2566 .texsubimage_faster_than_teximage),
2567 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2568 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2569 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2570 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2571 gpu_trace_level_(2),
2572 gpu_trace_commands_(false),
2573 gpu_debug_commands_(false),
2574 validation_texture_(0),
2575 validation_fbo_multisample_(0),
2576 validation_fbo_(0) {
2577 DCHECK(group);
2579 // The shader translator is used for WebGL even when running on EGL
2580 // because additional restrictions are needed (like only enabling
2581 // GL_OES_standard_derivatives on demand). It is used for the unit
2582 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2583 // the empty string to CompileShader and this is not a valid shader.
2584 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2585 base::CommandLine::ForCurrentProcess()->HasSwitch(
2586 switches::kDisableGLSLTranslator)) {
2587 use_shader_translator_ = false;
2591 GLES2DecoderImpl::~GLES2DecoderImpl() {
2594 bool GLES2DecoderImpl::Initialize(
2595 const scoped_refptr<gfx::GLSurface>& surface,
2596 const scoped_refptr<gfx::GLContext>& context,
2597 bool offscreen,
2598 const gfx::Size& offscreen_size,
2599 const DisallowedFeatures& disallowed_features,
2600 const std::vector<int32>& attribs) {
2601 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2602 DCHECK(context->IsCurrent(surface.get()));
2603 DCHECK(!context_.get());
2604 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2606 ContextCreationAttribHelper attrib_parser;
2607 if (!attrib_parser.Parse(attribs))
2608 return false;
2609 webgl_version_ = attrib_parser.webgl_version;
2611 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2613 set_initialized();
2614 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2616 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2617 switches::kEnableGPUDebugging)) {
2618 set_debug(true);
2621 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2622 switches::kEnableGPUCommandLogging)) {
2623 set_log_commands(true);
2626 compile_shader_always_succeeds_ =
2627 base::CommandLine::ForCurrentProcess()->HasSwitch(
2628 switches::kCompileShaderAlwaysSucceeds);
2630 // Take ownership of the context and surface. The surface can be replaced with
2631 // SetSurface.
2632 context_ = context;
2633 surface_ = surface;
2635 // Create GPU Tracer for timing values.
2636 gpu_tracer_.reset(new GPUTracer(this));
2638 if (feature_info_->workarounds().disable_timestamp_queries) {
2639 // Forcing time elapsed query for any GPU Timing Client forces it for all
2640 // clients in the context.
2641 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2644 // Save the loseContextWhenOutOfMemory context creation attribute.
2645 lose_context_when_out_of_memory_ =
2646 attrib_parser.lose_context_when_out_of_memory;
2648 // If the failIfMajorPerformanceCaveat context creation attribute was true
2649 // and we are using a software renderer, fail.
2650 if (attrib_parser.fail_if_major_perf_caveat &&
2651 feature_info_->feature_flags().is_swiftshader) {
2652 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2653 Destroy(true);
2654 return false;
2657 disallowed_features_ = disallowed_features;
2658 if (webgl_version_ == 1) {
2659 disallowed_features_.npot_support = true;
2662 if (!group_->Initialize(this,
2663 ContextGroup::GetContextType(webgl_version_),
2664 disallowed_features_)) {
2665 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2666 Destroy(true);
2667 return false;
2669 CHECK_GL_ERROR();
2671 if (webgl_version_ == 2) {
2672 if (!feature_info_->IsES3Capable()) {
2673 LOG(ERROR) << "Underlying driver does not support ES3.";
2674 Destroy(true);
2675 return false;
2677 feature_info_->EnableES3Validators();
2678 set_unsafe_es3_apis_enabled(true);
2681 state_.attrib_values.resize(group_->max_vertex_attribs());
2682 vertex_array_manager_.reset(new VertexArrayManager());
2684 GLuint default_vertex_attrib_service_id = 0;
2685 if (features().native_vertex_array_object) {
2686 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2687 glBindVertexArrayOES(default_vertex_attrib_service_id);
2690 state_.default_vertex_attrib_manager =
2691 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2693 state_.default_vertex_attrib_manager->Initialize(
2694 group_->max_vertex_attribs(),
2695 feature_info_->workarounds().init_vertex_attributes);
2697 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2698 DoBindVertexArrayOES(0);
2700 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2702 image_manager_.reset(new ImageManager);
2704 util_.set_num_compressed_texture_formats(
2705 validators_->compressed_texture_format.GetValues().size());
2707 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2708 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2709 // OpenGL ES 2.0 does not have this issue.
2710 glEnableVertexAttribArray(0);
2712 glGenBuffersARB(1, &attrib_0_buffer_id_);
2713 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2714 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2715 glBindBuffer(GL_ARRAY_BUFFER, 0);
2716 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2718 state_.texture_units.resize(group_->max_texture_units());
2719 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2720 glActiveTexture(GL_TEXTURE0 + tt);
2721 // We want the last bind to be 2D.
2722 TextureRef* ref;
2723 if (features().oes_egl_image_external) {
2724 ref = texture_manager()->GetDefaultTextureInfo(
2725 GL_TEXTURE_EXTERNAL_OES);
2726 state_.texture_units[tt].bound_texture_external_oes = ref;
2727 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2729 if (features().arb_texture_rectangle) {
2730 ref = texture_manager()->GetDefaultTextureInfo(
2731 GL_TEXTURE_RECTANGLE_ARB);
2732 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2733 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2735 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2736 state_.texture_units[tt].bound_texture_cube_map = ref;
2737 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2738 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2739 state_.texture_units[tt].bound_texture_2d = ref;
2740 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2742 glActiveTexture(GL_TEXTURE0);
2743 CHECK_GL_ERROR();
2745 // cache ALPHA_BITS result for re-use with clear behaviour
2746 GLint alpha_bits = 0;
2748 if (offscreen) {
2749 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2750 features().chromium_framebuffer_multisample) {
2751 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2752 // max_sample_count must be initialized to a sane value. If
2753 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2754 GLint max_sample_count = 1;
2755 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2756 offscreen_target_samples_ = std::min(attrib_parser.samples,
2757 max_sample_count);
2758 } else {
2759 offscreen_target_samples_ = 1;
2761 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2763 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2764 const bool rgb8_supported =
2765 context_->HasExtension("GL_OES_rgb8_rgba8");
2766 // The only available default render buffer formats in GLES2 have very
2767 // little precision. Don't enable multisampling unless 8-bit render
2768 // buffer formats are available--instead fall back to 8-bit textures.
2769 if (rgb8_supported && offscreen_target_samples_ > 1) {
2770 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2771 GL_RGBA8 : GL_RGB8;
2772 } else {
2773 offscreen_target_samples_ = 1;
2774 offscreen_target_color_format_ =
2775 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2776 ? GL_RGBA
2777 : GL_RGB;
2780 // ANGLE only supports packed depth/stencil formats, so use it if it is
2781 // available.
2782 const bool depth24_stencil8_supported =
2783 feature_info_->feature_flags().packed_depth24_stencil8;
2784 VLOG(1) << "GL_OES_packed_depth_stencil "
2785 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2786 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2787 depth24_stencil8_supported) {
2788 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2789 offscreen_target_stencil_format_ = 0;
2790 } else {
2791 // It may be the case that this depth/stencil combination is not
2792 // supported, but this will be checked later by CheckFramebufferStatus.
2793 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2794 GL_DEPTH_COMPONENT16 : 0;
2795 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2796 GL_STENCIL_INDEX8 : 0;
2798 } else {
2799 offscreen_target_color_format_ =
2800 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2801 ? GL_RGBA
2802 : GL_RGB;
2804 // If depth is requested at all, use the packed depth stencil format if
2805 // it's available, as some desktop GL drivers don't support any non-packed
2806 // formats for depth attachments.
2807 const bool depth24_stencil8_supported =
2808 feature_info_->feature_flags().packed_depth24_stencil8;
2809 VLOG(1) << "GL_EXT_packed_depth_stencil "
2810 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2812 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2813 depth24_stencil8_supported) {
2814 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2815 offscreen_target_stencil_format_ = 0;
2816 } else {
2817 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2818 GL_DEPTH_COMPONENT : 0;
2819 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2820 GL_STENCIL_INDEX : 0;
2824 offscreen_saved_color_format_ =
2825 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2826 ? GL_RGBA
2827 : GL_RGB;
2829 // Create the target frame buffer. This is the one that the client renders
2830 // directly to.
2831 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2832 offscreen_target_frame_buffer_->Create();
2833 // Due to GLES2 format limitations, either the color texture (for
2834 // non-multisampling) or the color render buffer (for multisampling) will be
2835 // attached to the offscreen frame buffer. The render buffer has more
2836 // limited formats available to it, but the texture can't do multisampling.
2837 if (IsOffscreenBufferMultisampled()) {
2838 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2839 renderbuffer_manager(), memory_tracker(), &state_));
2840 offscreen_target_color_render_buffer_->Create();
2841 } else {
2842 offscreen_target_color_texture_.reset(new BackTexture(
2843 memory_tracker(), &state_));
2844 offscreen_target_color_texture_->Create();
2846 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2847 renderbuffer_manager(), memory_tracker(), &state_));
2848 offscreen_target_depth_render_buffer_->Create();
2849 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2850 renderbuffer_manager(), memory_tracker(), &state_));
2851 offscreen_target_stencil_render_buffer_->Create();
2853 // Create the saved offscreen texture. The target frame buffer is copied
2854 // here when SwapBuffers is called.
2855 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2856 offscreen_saved_frame_buffer_->Create();
2858 offscreen_saved_color_texture_.reset(new BackTexture(
2859 memory_tracker(), &state_));
2860 offscreen_saved_color_texture_->Create();
2862 // Allocate the render buffers at their initial size and check the status
2863 // of the frame buffers is okay.
2864 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2865 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2866 Destroy(true);
2867 return false;
2870 state_.viewport_width = offscreen_size.width();
2871 state_.viewport_height = offscreen_size.height();
2873 // Allocate the offscreen saved color texture.
2874 DCHECK(offscreen_saved_color_format_);
2875 offscreen_saved_color_texture_->AllocateStorage(
2876 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2878 offscreen_saved_frame_buffer_->AttachRenderTexture(
2879 offscreen_saved_color_texture_.get());
2880 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2881 GL_FRAMEBUFFER_COMPLETE) {
2882 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2883 Destroy(true);
2884 return false;
2887 // Bind to the new default frame buffer (the offscreen target frame buffer).
2888 // This should now be associated with ID zero.
2889 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2890 } else {
2891 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2892 // These are NOT if the back buffer has these proprorties. They are
2893 // if we want the command buffer to enforce them regardless of what
2894 // the real backbuffer is assuming the real back buffer gives us more than
2895 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2896 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2897 // can't do anything about that.
2899 if (!surfaceless_) {
2900 GLint depth_bits = 0;
2901 GLint stencil_bits = 0;
2903 bool default_fb = (GetBackbufferServiceId() == 0);
2905 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2906 glGetFramebufferAttachmentParameterivEXT(
2907 GL_FRAMEBUFFER,
2908 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2909 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2910 glGetFramebufferAttachmentParameterivEXT(
2911 GL_FRAMEBUFFER,
2912 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2913 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2914 glGetFramebufferAttachmentParameterivEXT(
2915 GL_FRAMEBUFFER,
2916 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2917 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2918 } else {
2919 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2920 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2921 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2924 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2925 // the user requested RGB then RGB. If the user did not specify a
2926 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2927 back_buffer_color_format_ =
2928 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2929 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2930 back_buffer_has_stencil_ =
2931 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2934 state_.viewport_width = surface->GetSize().width();
2935 state_.viewport_height = surface->GetSize().height();
2938 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2939 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2940 // isn't well documented; it was discovered in the Khronos OpenGL ES
2941 // mailing list archives. It also implicitly enables the desktop GL
2942 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2943 // variable in fragment shaders.
2944 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2945 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2946 glEnable(GL_POINT_SPRITE);
2949 has_robustness_extension_ =
2950 context->HasExtension("GL_ARB_robustness") ||
2951 context->HasExtension("GL_KHR_robustness") ||
2952 context->HasExtension("GL_EXT_robustness");
2954 if (!InitializeShaderTranslator()) {
2955 return false;
2958 GLint viewport_params[4] = { 0 };
2959 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2960 viewport_max_width_ = viewport_params[0];
2961 viewport_max_height_ = viewport_params[1];
2963 state_.scissor_width = state_.viewport_width;
2964 state_.scissor_height = state_.viewport_height;
2966 // Set all the default state because some GL drivers get it wrong.
2967 state_.InitCapabilities(NULL);
2968 state_.InitState(NULL);
2969 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2971 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2972 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2973 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2974 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2975 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2977 bool call_gl_clear = !surfaceless_;
2978 #if defined(OS_ANDROID)
2979 // Temporary workaround for Android WebView because this clear ignores the
2980 // clip and corrupts that external UI of the App. Not calling glClear is ok
2981 // because the system already clears the buffer before each draw. Proper
2982 // fix might be setting the scissor clip properly before initialize. See
2983 // crbug.com/259023 for details.
2984 call_gl_clear = surface_->GetHandle();
2985 #endif
2986 if (call_gl_clear) {
2987 // On configs where we report no alpha, if the underlying surface has
2988 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2989 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
2990 if (clear_alpha) {
2991 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2994 // Clear the backbuffer.
2995 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2997 // Restore alpha clear value if we changed it.
2998 if (clear_alpha) {
2999 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3003 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
3004 if (feature_info_->workarounds()
3005 .disable_post_sub_buffers_for_onscreen_surfaces &&
3006 !surface->IsOffscreen())
3007 supports_post_sub_buffer_ = false;
3009 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
3010 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
3013 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3014 context_->SetUnbindFboOnMakeCurrent();
3017 // Only compositor contexts are known to use only the subset of GL
3018 // that can be safely migrated between the iGPU and the dGPU. Mark
3019 // those contexts as safe to forcibly transition between the GPUs.
3020 // http://crbug.com/180876, http://crbug.com/227228
3021 if (!offscreen)
3022 context_->SetSafeToForceGpuSwitch();
3024 async_pixel_transfer_manager_.reset(
3025 AsyncPixelTransferManager::Create(context.get()));
3026 async_pixel_transfer_manager_->Initialize(texture_manager());
3028 if (workarounds().gl_clear_broken) {
3029 DCHECK(!clear_framebuffer_blit_.get());
3030 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3031 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3032 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3033 return false;
3036 framebuffer_manager()->AddObserver(this);
3038 return true;
3041 Capabilities GLES2DecoderImpl::GetCapabilities() {
3042 DCHECK(initialized());
3043 Capabilities caps;
3044 caps.VisitPrecisions([](GLenum shader, GLenum type,
3045 Capabilities::ShaderPrecision* shader_precision) {
3046 GLint range[2] = {0, 0};
3047 GLint precision = 0;
3048 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3049 shader_precision->min_range = range[0];
3050 shader_precision->max_range = range[1];
3051 shader_precision->precision = precision;
3053 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3054 &caps.max_combined_texture_image_units);
3055 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3056 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3057 &caps.max_fragment_uniform_vectors);
3058 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3059 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3060 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3061 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3062 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3063 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3064 &caps.max_vertex_texture_image_units);
3065 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3066 &caps.max_vertex_uniform_vectors);
3067 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3068 &caps.num_compressed_texture_formats);
3069 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3070 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3071 &caps.bind_generates_resource_chromium);
3072 if (unsafe_es3_apis_enabled()) {
3073 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3074 // but for now we clamp them to 32-bit max.
3075 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3076 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3077 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3078 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3079 &caps.max_combined_fragment_uniform_components);
3080 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3081 &caps.max_combined_uniform_blocks);
3082 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3083 &caps.max_combined_vertex_uniform_components);
3084 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3085 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3086 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3087 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3088 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3089 &caps.max_fragment_input_components);
3090 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3091 &caps.max_fragment_uniform_blocks);
3092 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3093 &caps.max_fragment_uniform_components);
3094 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3095 &caps.max_program_texel_offset);
3096 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3097 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3098 // returned.
3099 if (caps.max_server_wait_timeout < 0)
3100 caps.max_server_wait_timeout = 0;
3101 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3102 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3103 &caps.max_transform_feedback_interleaved_components);
3104 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3105 &caps.max_transform_feedback_separate_attribs);
3106 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3107 &caps.max_transform_feedback_separate_components);
3108 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3109 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3110 &caps.max_uniform_buffer_bindings);
3111 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3112 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3113 &caps.max_vertex_output_components);
3114 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3115 &caps.max_vertex_uniform_blocks);
3116 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3117 &caps.max_vertex_uniform_components);
3118 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3119 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3120 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3121 &caps.num_program_binary_formats);
3122 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3123 &caps.uniform_buffer_offset_alignment);
3124 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3125 caps.major_version = 3;
3126 caps.minor_version = 0;
3128 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3129 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3130 unsafe_es3_apis_enabled()) {
3131 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3134 caps.egl_image_external =
3135 feature_info_->feature_flags().oes_egl_image_external;
3136 caps.texture_format_atc =
3137 feature_info_->feature_flags().ext_texture_format_atc;
3138 caps.texture_format_bgra8888 =
3139 feature_info_->feature_flags().ext_texture_format_bgra8888;
3140 caps.texture_format_dxt1 =
3141 feature_info_->feature_flags().ext_texture_format_dxt1;
3142 caps.texture_format_dxt5 =
3143 feature_info_->feature_flags().ext_texture_format_dxt5;
3144 caps.texture_format_etc1 =
3145 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3146 caps.texture_format_etc1_npot =
3147 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3148 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3149 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3150 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3151 caps.discard_framebuffer =
3152 feature_info_->feature_flags().ext_discard_framebuffer;
3153 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3155 #if defined(OS_MACOSX)
3156 // This is unconditionally true on mac, no need to test for it at runtime.
3157 caps.iosurface = true;
3158 #endif
3160 caps.post_sub_buffer = supports_post_sub_buffer_;
3161 caps.image = true;
3162 caps.surfaceless = surfaceless_;
3164 caps.blend_equation_advanced =
3165 feature_info_->feature_flags().blend_equation_advanced;
3166 caps.blend_equation_advanced_coherent =
3167 feature_info_->feature_flags().blend_equation_advanced_coherent;
3168 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3169 caps.max_copy_texture_chromium_size =
3170 feature_info_->workarounds().max_copy_texture_chromium_size;
3171 caps.render_buffer_format_bgra8888 =
3172 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3173 caps.occlusion_query_boolean =
3174 feature_info_->feature_flags().occlusion_query_boolean;
3175 caps.timer_queries =
3176 query_manager_->GPUTimingAvailable();
3177 return caps;
3180 void GLES2DecoderImpl::UpdateCapabilities() {
3181 util_.set_num_compressed_texture_formats(
3182 validators_->compressed_texture_format.GetValues().size());
3183 util_.set_num_shader_binary_formats(
3184 validators_->shader_binary_format.GetValues().size());
3187 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3188 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3190 if (!use_shader_translator_) {
3191 return true;
3193 ShBuiltInResources resources;
3194 ShInitBuiltInResources(&resources);
3195 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3196 resources.MaxVertexUniformVectors =
3197 group_->max_vertex_uniform_vectors();
3198 resources.MaxVaryingVectors = group_->max_varying_vectors();
3199 resources.MaxVertexTextureImageUnits =
3200 group_->max_vertex_texture_image_units();
3201 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3202 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3203 resources.MaxFragmentUniformVectors =
3204 group_->max_fragment_uniform_vectors();
3205 resources.MaxDrawBuffers = group_->max_draw_buffers();
3206 resources.MaxExpressionComplexity = 256;
3207 resources.MaxCallStackDepth = 256;
3209 GLint range[2] = { 0, 0 };
3210 GLint precision = 0;
3211 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3212 range, &precision);
3213 resources.FragmentPrecisionHigh =
3214 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3216 if (IsWebGLContext()) {
3217 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3218 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3219 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3220 if (!draw_buffers_explicitly_enabled_)
3221 resources.MaxDrawBuffers = 1;
3222 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3223 resources.NV_draw_buffers =
3224 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3225 } else {
3226 resources.OES_standard_derivatives =
3227 features().oes_standard_derivatives ? 1 : 0;
3228 resources.ARB_texture_rectangle =
3229 features().arb_texture_rectangle ? 1 : 0;
3230 resources.OES_EGL_image_external =
3231 features().oes_egl_image_external ? 1 : 0;
3232 resources.EXT_draw_buffers =
3233 features().ext_draw_buffers ? 1 : 0;
3234 resources.EXT_frag_depth =
3235 features().ext_frag_depth ? 1 : 0;
3236 resources.EXT_shader_texture_lod =
3237 features().ext_shader_texture_lod ? 1 : 0;
3238 resources.NV_draw_buffers =
3239 features().nv_draw_buffers ? 1 : 0;
3242 ShShaderSpec shader_spec;
3243 if (IsWebGLContext()) {
3244 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3245 } else {
3246 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3249 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3250 features().enable_shader_name_hashing)
3251 resources.HashFunction = &CityHash64;
3252 else
3253 resources.HashFunction = NULL;
3254 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3255 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3256 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3257 int driver_bug_workarounds = 0;
3258 if (workarounds().needs_glsl_built_in_function_emulation)
3259 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3260 if (workarounds().init_gl_position_in_vertex_shader)
3261 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3262 if (workarounds().unfold_short_circuit_as_ternary_operation)
3263 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3264 if (workarounds().init_varyings_without_static_use)
3265 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3266 if (workarounds().unroll_for_loop_with_sampler_array_index)
3267 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3268 if (workarounds().scalarize_vec_and_mat_constructor_args)
3269 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3270 if (workarounds().regenerate_struct_names)
3271 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3272 if (workarounds().remove_pow_with_constant_exponent)
3273 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3275 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3276 switches::kEmulateShaderPrecision))
3277 resources.WEBGL_debug_shader_precision = true;
3279 vertex_translator_ = shader_translator_cache()->GetTranslator(
3280 GL_VERTEX_SHADER,
3281 shader_spec,
3282 &resources,
3283 implementation_type,
3284 static_cast<ShCompileOptions>(driver_bug_workarounds));
3285 if (!vertex_translator_.get()) {
3286 LOG(ERROR) << "Could not initialize vertex shader translator.";
3287 Destroy(true);
3288 return false;
3291 fragment_translator_ = shader_translator_cache()->GetTranslator(
3292 GL_FRAGMENT_SHADER,
3293 shader_spec,
3294 &resources,
3295 implementation_type,
3296 static_cast<ShCompileOptions>(driver_bug_workarounds));
3297 if (!fragment_translator_.get()) {
3298 LOG(ERROR) << "Could not initialize fragment shader translator.";
3299 Destroy(true);
3300 return false;
3302 return true;
3305 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3306 for (GLsizei ii = 0; ii < n; ++ii) {
3307 if (GetBuffer(client_ids[ii])) {
3308 return false;
3311 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3312 glGenBuffersARB(n, service_ids.get());
3313 for (GLsizei ii = 0; ii < n; ++ii) {
3314 CreateBuffer(client_ids[ii], service_ids[ii]);
3316 return true;
3319 bool GLES2DecoderImpl::GenFramebuffersHelper(
3320 GLsizei n, const GLuint* client_ids) {
3321 for (GLsizei ii = 0; ii < n; ++ii) {
3322 if (GetFramebuffer(client_ids[ii])) {
3323 return false;
3326 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3327 glGenFramebuffersEXT(n, service_ids.get());
3328 for (GLsizei ii = 0; ii < n; ++ii) {
3329 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3331 return true;
3334 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3335 GLsizei n, const GLuint* client_ids) {
3336 for (GLsizei ii = 0; ii < n; ++ii) {
3337 if (GetRenderbuffer(client_ids[ii])) {
3338 return false;
3341 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3342 glGenRenderbuffersEXT(n, service_ids.get());
3343 for (GLsizei ii = 0; ii < n; ++ii) {
3344 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3346 return true;
3349 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3350 const GLuint* client_ids) {
3351 for (GLsizei ii = 0; ii < n; ++ii) {
3352 if (GetValuebuffer(client_ids[ii])) {
3353 return false;
3356 for (GLsizei ii = 0; ii < n; ++ii) {
3357 CreateValuebuffer(client_ids[ii]);
3359 return true;
3362 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3363 for (GLsizei ii = 0; ii < n; ++ii) {
3364 if (GetTexture(client_ids[ii])) {
3365 return false;
3368 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3369 glGenTextures(n, service_ids.get());
3370 for (GLsizei ii = 0; ii < n; ++ii) {
3371 CreateTexture(client_ids[ii], service_ids[ii]);
3373 return true;
3376 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3377 GLsizei range) {
3378 GLuint last_client_id;
3379 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3380 return false;
3382 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3383 return false;
3385 GLuint first_service_id = glGenPathsNV(range);
3386 if (first_service_id == 0) {
3387 // We have to fail the connection here, because client has already
3388 // succeeded in allocating the ids. This happens if we allocate
3389 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3390 // example).
3391 return false;
3393 // GenPathsNV does not wrap.
3394 DCHECK(first_service_id + range - 1 >= first_service_id);
3396 path_manager()->CreatePathRange(first_client_id, last_client_id,
3397 first_service_id);
3399 return true;
3402 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3403 GLsizei range) {
3404 GLuint last_client_id;
3405 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3406 return false;
3408 path_manager()->RemovePaths(first_client_id, last_client_id);
3409 return true;
3412 void GLES2DecoderImpl::DeleteBuffersHelper(
3413 GLsizei n, const GLuint* client_ids) {
3414 for (GLsizei ii = 0; ii < n; ++ii) {
3415 Buffer* buffer = GetBuffer(client_ids[ii]);
3416 if (buffer && !buffer->IsDeleted()) {
3417 buffer->RemoveMappedRange();
3418 state_.RemoveBoundBuffer(buffer);
3419 RemoveBuffer(client_ids[ii]);
3424 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3425 GLsizei n, const GLuint* client_ids) {
3426 bool supports_separate_framebuffer_binds =
3427 features().chromium_framebuffer_multisample;
3429 for (GLsizei ii = 0; ii < n; ++ii) {
3430 Framebuffer* framebuffer =
3431 GetFramebuffer(client_ids[ii]);
3432 if (framebuffer && !framebuffer->IsDeleted()) {
3433 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3434 GLenum target = supports_separate_framebuffer_binds ?
3435 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3437 // Unbind attachments on FBO before deletion.
3438 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3439 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3441 glBindFramebufferEXT(target, GetBackbufferServiceId());
3442 framebuffer_state_.bound_draw_framebuffer = NULL;
3443 framebuffer_state_.clear_state_dirty = true;
3445 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3446 framebuffer_state_.bound_read_framebuffer = NULL;
3447 GLenum target = supports_separate_framebuffer_binds ?
3448 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3449 glBindFramebufferEXT(target, GetBackbufferServiceId());
3451 OnFboChanged();
3452 RemoveFramebuffer(client_ids[ii]);
3457 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3458 GLsizei n, const GLuint* client_ids) {
3459 bool supports_separate_framebuffer_binds =
3460 features().chromium_framebuffer_multisample;
3461 for (GLsizei ii = 0; ii < n; ++ii) {
3462 Renderbuffer* renderbuffer =
3463 GetRenderbuffer(client_ids[ii]);
3464 if (renderbuffer && !renderbuffer->IsDeleted()) {
3465 if (state_.bound_renderbuffer.get() == renderbuffer) {
3466 state_.bound_renderbuffer = NULL;
3468 // Unbind from current framebuffers.
3469 if (supports_separate_framebuffer_binds) {
3470 if (framebuffer_state_.bound_read_framebuffer.get()) {
3471 framebuffer_state_.bound_read_framebuffer
3472 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3474 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3475 framebuffer_state_.bound_draw_framebuffer
3476 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3478 } else {
3479 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3480 framebuffer_state_.bound_draw_framebuffer
3481 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3484 framebuffer_state_.clear_state_dirty = true;
3485 RemoveRenderbuffer(client_ids[ii]);
3490 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3491 GLsizei n,
3492 const GLuint* client_ids) {
3493 for (GLsizei ii = 0; ii < n; ++ii) {
3494 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3495 if (valuebuffer) {
3496 if (state_.bound_valuebuffer.get() == valuebuffer) {
3497 state_.bound_valuebuffer = NULL;
3499 RemoveValuebuffer(client_ids[ii]);
3504 void GLES2DecoderImpl::DeleteTexturesHelper(
3505 GLsizei n, const GLuint* client_ids) {
3506 bool supports_separate_framebuffer_binds =
3507 features().chromium_framebuffer_multisample;
3508 for (GLsizei ii = 0; ii < n; ++ii) {
3509 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3510 if (texture_ref) {
3511 Texture* texture = texture_ref->texture();
3512 if (texture->IsAttachedToFramebuffer()) {
3513 framebuffer_state_.clear_state_dirty = true;
3515 // Unbind texture_ref from texture_ref units.
3516 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3517 state_.texture_units[jj].Unbind(texture_ref);
3519 // Unbind from current framebuffers.
3520 if (supports_separate_framebuffer_binds) {
3521 if (framebuffer_state_.bound_read_framebuffer.get()) {
3522 framebuffer_state_.bound_read_framebuffer
3523 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3525 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3526 framebuffer_state_.bound_draw_framebuffer
3527 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3529 } else {
3530 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3531 framebuffer_state_.bound_draw_framebuffer
3532 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3535 #if defined(OS_MACOSX)
3536 GLuint service_id = texture->service_id();
3537 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3538 ReleaseIOSurfaceForTexture(service_id);
3540 #endif
3541 RemoveTexture(client_ids[ii]);
3546 // } // anonymous namespace
3548 bool GLES2DecoderImpl::MakeCurrent() {
3549 if (!context_.get())
3550 return false;
3552 if (WasContextLost()) {
3553 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3554 return false;
3557 if (!context_->MakeCurrent(surface_.get())) {
3558 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3559 MarkContextLost(error::kMakeCurrentFailed);
3560 group_->LoseContexts(error::kUnknown);
3561 return false;
3564 if (CheckResetStatus()) {
3565 LOG(ERROR)
3566 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3567 group_->LoseContexts(error::kUnknown);
3568 return false;
3571 ProcessFinishedAsyncTransfers();
3573 // Rebind the FBO if it was unbound by the context.
3574 if (workarounds().unbind_fbo_on_context_switch)
3575 RestoreFramebufferBindings();
3577 framebuffer_state_.clear_state_dirty = true;
3579 return true;
3582 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3583 ProcessPendingReadPixels(false);
3584 if (engine() && query_manager_.get())
3585 query_manager_->ProcessPendingTransferQueries();
3587 // TODO(epenner): Is there a better place to do this?
3588 // This needs to occur before we execute any batch of commands
3589 // from the client, as the client may have recieved an async
3590 // completion while issuing those commands.
3591 // "DidFlushStart" would be ideal if we had such a callback.
3592 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3595 static void RebindCurrentFramebuffer(
3596 GLenum target,
3597 Framebuffer* framebuffer,
3598 GLuint back_buffer_service_id) {
3599 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3601 if (framebuffer_id == 0) {
3602 framebuffer_id = back_buffer_service_id;
3605 glBindFramebufferEXT(target, framebuffer_id);
3608 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3609 framebuffer_state_.clear_state_dirty = true;
3611 if (!features().chromium_framebuffer_multisample) {
3612 RebindCurrentFramebuffer(
3613 GL_FRAMEBUFFER,
3614 framebuffer_state_.bound_draw_framebuffer.get(),
3615 GetBackbufferServiceId());
3616 } else {
3617 RebindCurrentFramebuffer(
3618 GL_READ_FRAMEBUFFER_EXT,
3619 framebuffer_state_.bound_read_framebuffer.get(),
3620 GetBackbufferServiceId());
3621 RebindCurrentFramebuffer(
3622 GL_DRAW_FRAMEBUFFER_EXT,
3623 framebuffer_state_.bound_draw_framebuffer.get(),
3624 GetBackbufferServiceId());
3626 OnFboChanged();
3629 bool GLES2DecoderImpl::CheckFramebufferValid(
3630 Framebuffer* framebuffer,
3631 GLenum target, const char* func_name) {
3632 if (!framebuffer) {
3633 if (surfaceless_)
3634 return false;
3635 if (backbuffer_needs_clear_bits_) {
3636 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3637 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3638 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3639 glClearStencil(0);
3640 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3641 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3642 glClearDepth(1.0f);
3643 state_.SetDeviceDepthMask(GL_TRUE);
3644 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3645 bool reset_draw_buffer = false;
3646 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3647 group_->draw_buffer() == GL_NONE) {
3648 reset_draw_buffer = true;
3649 GLenum buf = GL_BACK;
3650 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3651 buf = GL_COLOR_ATTACHMENT0;
3652 glDrawBuffersARB(1, &buf);
3654 glClear(backbuffer_needs_clear_bits_);
3655 if (reset_draw_buffer) {
3656 GLenum buf = GL_NONE;
3657 glDrawBuffersARB(1, &buf);
3659 backbuffer_needs_clear_bits_ = 0;
3660 RestoreClearState();
3662 return true;
3665 if (framebuffer_manager()->IsComplete(framebuffer)) {
3666 return true;
3669 GLenum completeness = framebuffer->IsPossiblyComplete();
3670 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3671 LOCAL_SET_GL_ERROR(
3672 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3673 return false;
3676 // Are all the attachments cleared?
3677 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3678 texture_manager()->HaveUnclearedMips()) {
3679 if (!framebuffer->IsCleared()) {
3680 // Can we clear them?
3681 if (framebuffer->GetStatus(texture_manager(), target) !=
3682 GL_FRAMEBUFFER_COMPLETE) {
3683 LOCAL_SET_GL_ERROR(
3684 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3685 "framebuffer incomplete (clear)");
3686 return false;
3688 ClearUnclearedAttachments(target, framebuffer);
3692 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3693 if (framebuffer->GetStatus(texture_manager(), target) !=
3694 GL_FRAMEBUFFER_COMPLETE) {
3695 LOCAL_SET_GL_ERROR(
3696 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3697 "framebuffer incomplete (check)");
3698 return false;
3700 framebuffer_manager()->MarkAsComplete(framebuffer);
3703 // NOTE: At this point we don't know if the framebuffer is complete but
3704 // we DO know that everything that needs to be cleared has been cleared.
3705 return true;
3708 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3709 if (!features().chromium_framebuffer_multisample) {
3710 bool valid = CheckFramebufferValid(
3711 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3712 func_name);
3714 if (valid)
3715 OnUseFramebuffer();
3717 return valid;
3719 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3720 GL_DRAW_FRAMEBUFFER_EXT,
3721 func_name) &&
3722 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3723 GL_READ_FRAMEBUFFER_EXT,
3724 func_name);
3727 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3728 const char* func_name) {
3729 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3730 framebuffer_state_.bound_read_framebuffer.get() :
3731 framebuffer_state_.bound_draw_framebuffer.get();
3732 if (!framebuffer)
3733 return true;
3734 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3735 LOCAL_SET_GL_ERROR(
3736 GL_INVALID_OPERATION, func_name, "no color image attached");
3737 return false;
3739 return true;
3742 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3743 TextureRef* texture, GLint level) {
3744 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3745 framebuffer_state_.bound_read_framebuffer.get() :
3746 framebuffer_state_.bound_draw_framebuffer.get();
3747 if (!framebuffer)
3748 return false;
3749 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3750 GL_COLOR_ATTACHMENT0);
3751 if (!attachment)
3752 return false;
3753 return attachment->FormsFeedbackLoop(texture, level);
3756 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3757 Framebuffer* framebuffer =
3758 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3759 if (framebuffer != NULL) {
3760 const Framebuffer::Attachment* attachment =
3761 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3762 if (attachment) {
3763 return gfx::Size(attachment->width(), attachment->height());
3765 return gfx::Size(0, 0);
3766 } else if (offscreen_target_frame_buffer_.get()) {
3767 return offscreen_size_;
3768 } else {
3769 return surface_->GetSize();
3773 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3774 Framebuffer* framebuffer =
3775 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3776 if (framebuffer != NULL) {
3777 return framebuffer->GetColorAttachmentTextureType();
3778 } else {
3779 return GL_UNSIGNED_BYTE;
3783 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3784 Framebuffer* framebuffer =
3785 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3786 if (framebuffer != NULL) {
3787 return framebuffer->GetColorAttachmentFormat();
3788 } else if (offscreen_target_frame_buffer_.get()) {
3789 return offscreen_target_color_format_;
3790 } else {
3791 return back_buffer_color_format_;
3795 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3796 Framebuffer* framebuffer =
3797 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3798 if (framebuffer != NULL) {
3799 return framebuffer->GetColorAttachmentFormat();
3800 } else if (offscreen_target_frame_buffer_.get()) {
3801 return offscreen_target_color_format_;
3802 } else {
3803 return back_buffer_color_format_;
3807 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3808 if (!offscreen_saved_color_texture_info_.get())
3809 return;
3810 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3811 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3812 texture_manager()->SetLevelInfo(
3813 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3814 0, // level
3815 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3816 1, // depth
3817 0, // border
3818 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3819 texture_manager()->SetParameteri(
3820 "UpdateParentTextureInfo",
3821 GetErrorState(),
3822 offscreen_saved_color_texture_info_.get(),
3823 GL_TEXTURE_MAG_FILTER,
3824 GL_LINEAR);
3825 texture_manager()->SetParameteri(
3826 "UpdateParentTextureInfo",
3827 GetErrorState(),
3828 offscreen_saved_color_texture_info_.get(),
3829 GL_TEXTURE_MIN_FILTER,
3830 GL_LINEAR);
3831 texture_manager()->SetParameteri(
3832 "UpdateParentTextureInfo",
3833 GetErrorState(),
3834 offscreen_saved_color_texture_info_.get(),
3835 GL_TEXTURE_WRAP_S,
3836 GL_CLAMP_TO_EDGE);
3837 texture_manager()->SetParameteri(
3838 "UpdateParentTextureInfo",
3839 GetErrorState(),
3840 offscreen_saved_color_texture_info_.get(),
3841 GL_TEXTURE_WRAP_T,
3842 GL_CLAMP_TO_EDGE);
3843 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3844 &state_, target);
3845 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3848 void GLES2DecoderImpl::SetResizeCallback(
3849 const base::Callback<void(gfx::Size, float)>& callback) {
3850 resize_callback_ = callback;
3853 Logger* GLES2DecoderImpl::GetLogger() {
3854 return &logger_;
3857 void GLES2DecoderImpl::BeginDecoding() {
3858 gpu_tracer_->BeginDecoding();
3859 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3860 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3861 (*cb_command_trace_category_ != 0);
3862 query_manager_->ProcessFrameBeginUpdates();
3865 void GLES2DecoderImpl::EndDecoding() {
3866 gpu_tracer_->EndDecoding();
3869 ErrorState* GLES2DecoderImpl::GetErrorState() {
3870 return state_.GetErrorState();
3873 void GLES2DecoderImpl::SetShaderCacheCallback(
3874 const ShaderCacheCallback& callback) {
3875 shader_cache_callback_ = callback;
3878 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3879 const WaitSyncPointCallback& callback) {
3880 wait_sync_point_callback_ = callback;
3883 AsyncPixelTransferManager*
3884 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3885 return async_pixel_transfer_manager_.get();
3888 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3889 async_pixel_transfer_manager_.reset();
3892 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3893 AsyncPixelTransferManager* manager) {
3894 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3897 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3898 uint32* service_texture_id) {
3899 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3900 if (texture_ref) {
3901 *service_texture_id = texture_ref->service_id();
3902 return true;
3904 return false;
3907 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3908 return texture_state_.texture_upload_count +
3909 async_pixel_transfer_manager_->GetTextureUploadCount();
3912 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3913 return texture_state_.total_texture_upload_time +
3914 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3917 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3918 return total_processing_commands_time_;
3921 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3922 total_processing_commands_time_ += time;
3925 void GLES2DecoderImpl::Destroy(bool have_context) {
3926 if (!initialized())
3927 return;
3929 DCHECK(!have_context || context_->IsCurrent(NULL));
3931 // Unbind everything.
3932 state_.vertex_attrib_manager = NULL;
3933 state_.default_vertex_attrib_manager = NULL;
3934 state_.texture_units.clear();
3935 state_.bound_array_buffer = NULL;
3936 state_.bound_copy_read_buffer = NULL;
3937 state_.bound_copy_write_buffer = NULL;
3938 state_.bound_pixel_pack_buffer = NULL;
3939 state_.bound_pixel_unpack_buffer = NULL;
3940 state_.bound_transform_feedback_buffer = NULL;
3941 state_.bound_uniform_buffer = NULL;
3942 framebuffer_state_.bound_read_framebuffer = NULL;
3943 framebuffer_state_.bound_draw_framebuffer = NULL;
3944 state_.bound_renderbuffer = NULL;
3945 state_.bound_valuebuffer = NULL;
3947 if (offscreen_saved_color_texture_info_.get()) {
3948 DCHECK(offscreen_target_color_texture_);
3949 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3950 offscreen_saved_color_texture_->id());
3951 offscreen_saved_color_texture_->Invalidate();
3952 offscreen_saved_color_texture_info_ = NULL;
3954 if (have_context) {
3955 if (copy_texture_CHROMIUM_.get()) {
3956 copy_texture_CHROMIUM_->Destroy();
3957 copy_texture_CHROMIUM_.reset();
3960 clear_framebuffer_blit_.reset();
3962 if (state_.current_program.get()) {
3963 program_manager()->UnuseProgram(shader_manager(),
3964 state_.current_program.get());
3967 if (attrib_0_buffer_id_) {
3968 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3970 if (fixed_attrib_buffer_id_) {
3971 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3974 if (validation_texture_) {
3975 glDeleteTextures(1, &validation_texture_);
3976 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3977 glDeleteFramebuffersEXT(1, &validation_fbo_);
3980 if (offscreen_target_frame_buffer_.get())
3981 offscreen_target_frame_buffer_->Destroy();
3982 if (offscreen_target_color_texture_.get())
3983 offscreen_target_color_texture_->Destroy();
3984 if (offscreen_target_color_render_buffer_.get())
3985 offscreen_target_color_render_buffer_->Destroy();
3986 if (offscreen_target_depth_render_buffer_.get())
3987 offscreen_target_depth_render_buffer_->Destroy();
3988 if (offscreen_target_stencil_render_buffer_.get())
3989 offscreen_target_stencil_render_buffer_->Destroy();
3990 if (offscreen_saved_frame_buffer_.get())
3991 offscreen_saved_frame_buffer_->Destroy();
3992 if (offscreen_saved_color_texture_.get())
3993 offscreen_saved_color_texture_->Destroy();
3994 if (offscreen_resolved_frame_buffer_.get())
3995 offscreen_resolved_frame_buffer_->Destroy();
3996 if (offscreen_resolved_color_texture_.get())
3997 offscreen_resolved_color_texture_->Destroy();
3998 } else {
3999 if (offscreen_target_frame_buffer_.get())
4000 offscreen_target_frame_buffer_->Invalidate();
4001 if (offscreen_target_color_texture_.get())
4002 offscreen_target_color_texture_->Invalidate();
4003 if (offscreen_target_color_render_buffer_.get())
4004 offscreen_target_color_render_buffer_->Invalidate();
4005 if (offscreen_target_depth_render_buffer_.get())
4006 offscreen_target_depth_render_buffer_->Invalidate();
4007 if (offscreen_target_stencil_render_buffer_.get())
4008 offscreen_target_stencil_render_buffer_->Invalidate();
4009 if (offscreen_saved_frame_buffer_.get())
4010 offscreen_saved_frame_buffer_->Invalidate();
4011 if (offscreen_saved_color_texture_.get())
4012 offscreen_saved_color_texture_->Invalidate();
4013 if (offscreen_resolved_frame_buffer_.get())
4014 offscreen_resolved_frame_buffer_->Invalidate();
4015 if (offscreen_resolved_color_texture_.get())
4016 offscreen_resolved_color_texture_->Invalidate();
4019 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4020 // Otherwise, we can leak objects. http://crbug.com/258772.
4021 // state_.current_program must be reset before group_ is reset because
4022 // the later deletes the ProgramManager object that referred by
4023 // state_.current_program object.
4024 state_.current_program = NULL;
4026 copy_texture_CHROMIUM_.reset();
4027 clear_framebuffer_blit_.reset();
4029 if (query_manager_.get()) {
4030 query_manager_->Destroy(have_context);
4031 query_manager_.reset();
4034 if (vertex_array_manager_ .get()) {
4035 vertex_array_manager_->Destroy(have_context);
4036 vertex_array_manager_.reset();
4039 if (image_manager_.get()) {
4040 image_manager_->Destroy(have_context);
4041 image_manager_.reset();
4044 offscreen_target_frame_buffer_.reset();
4045 offscreen_target_color_texture_.reset();
4046 offscreen_target_color_render_buffer_.reset();
4047 offscreen_target_depth_render_buffer_.reset();
4048 offscreen_target_stencil_render_buffer_.reset();
4049 offscreen_saved_frame_buffer_.reset();
4050 offscreen_saved_color_texture_.reset();
4051 offscreen_resolved_frame_buffer_.reset();
4052 offscreen_resolved_color_texture_.reset();
4054 // Need to release these before releasing |group_| which may own the
4055 // ShaderTranslatorCache.
4056 fragment_translator_ = NULL;
4057 vertex_translator_ = NULL;
4059 // Should destroy the transfer manager before the texture manager held
4060 // by the context group.
4061 async_pixel_transfer_manager_.reset();
4063 // Destroy the GPU Tracer which may own some in process GPU Timings.
4064 if (gpu_tracer_) {
4065 gpu_tracer_->Destroy(have_context);
4066 gpu_tracer_.reset();
4069 if (group_.get()) {
4070 framebuffer_manager()->RemoveObserver(this);
4071 group_->Destroy(this, have_context);
4072 group_ = NULL;
4075 if (context_.get()) {
4076 context_->ReleaseCurrent(NULL);
4077 context_ = NULL;
4080 #if defined(OS_MACOSX)
4081 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4082 it != texture_to_io_surface_map_.end(); ++it) {
4083 CFRelease(it->second);
4085 texture_to_io_surface_map_.clear();
4086 #endif
4089 void GLES2DecoderImpl::SetSurface(
4090 const scoped_refptr<gfx::GLSurface>& surface) {
4091 DCHECK(context_->IsCurrent(NULL));
4092 DCHECK(surface_.get());
4093 surface_ = surface;
4094 RestoreCurrentFramebufferBindings();
4097 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4098 if (!offscreen_saved_color_texture_.get()) {
4099 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4100 return;
4102 if (!offscreen_saved_color_texture_info_.get()) {
4103 GLuint service_id = offscreen_saved_color_texture_->id();
4104 offscreen_saved_color_texture_info_ = TextureRef::Create(
4105 texture_manager(), 0, service_id);
4106 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4107 GL_TEXTURE_2D);
4108 UpdateParentTextureInfo();
4110 mailbox_manager()->ProduceTexture(
4111 mailbox, offscreen_saved_color_texture_info_->texture());
4114 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4115 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4116 if (!is_offscreen) {
4117 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4118 << " with an onscreen framebuffer.";
4119 return false;
4122 if (offscreen_size_ == size)
4123 return true;
4125 offscreen_size_ = size;
4126 int w = offscreen_size_.width();
4127 int h = offscreen_size_.height();
4128 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4129 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4130 << "to allocate storage due to excessive dimensions.";
4131 return false;
4134 // Reallocate the offscreen target buffers.
4135 DCHECK(offscreen_target_color_format_);
4136 if (IsOffscreenBufferMultisampled()) {
4137 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4138 feature_info_.get(),
4139 offscreen_size_,
4140 offscreen_target_color_format_,
4141 offscreen_target_samples_)) {
4142 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4143 << "to allocate storage for offscreen target color buffer.";
4144 return false;
4146 } else {
4147 if (!offscreen_target_color_texture_->AllocateStorage(
4148 offscreen_size_, offscreen_target_color_format_, false)) {
4149 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4150 << "to allocate storage for offscreen target color texture.";
4151 return false;
4154 if (offscreen_target_depth_format_ &&
4155 !offscreen_target_depth_render_buffer_->AllocateStorage(
4156 feature_info_.get(),
4157 offscreen_size_,
4158 offscreen_target_depth_format_,
4159 offscreen_target_samples_)) {
4160 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4161 << "to allocate storage for offscreen target depth buffer.";
4162 return false;
4164 if (offscreen_target_stencil_format_ &&
4165 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4166 feature_info_.get(),
4167 offscreen_size_,
4168 offscreen_target_stencil_format_,
4169 offscreen_target_samples_)) {
4170 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4171 << "to allocate storage for offscreen target stencil buffer.";
4172 return false;
4175 // Attach the offscreen target buffers to the target frame buffer.
4176 if (IsOffscreenBufferMultisampled()) {
4177 offscreen_target_frame_buffer_->AttachRenderBuffer(
4178 GL_COLOR_ATTACHMENT0,
4179 offscreen_target_color_render_buffer_.get());
4180 } else {
4181 offscreen_target_frame_buffer_->AttachRenderTexture(
4182 offscreen_target_color_texture_.get());
4184 if (offscreen_target_depth_format_) {
4185 offscreen_target_frame_buffer_->AttachRenderBuffer(
4186 GL_DEPTH_ATTACHMENT,
4187 offscreen_target_depth_render_buffer_.get());
4189 const bool packed_depth_stencil =
4190 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4191 if (packed_depth_stencil) {
4192 offscreen_target_frame_buffer_->AttachRenderBuffer(
4193 GL_STENCIL_ATTACHMENT,
4194 offscreen_target_depth_render_buffer_.get());
4195 } else if (offscreen_target_stencil_format_) {
4196 offscreen_target_frame_buffer_->AttachRenderBuffer(
4197 GL_STENCIL_ATTACHMENT,
4198 offscreen_target_stencil_render_buffer_.get());
4201 if (offscreen_target_frame_buffer_->CheckStatus() !=
4202 GL_FRAMEBUFFER_COMPLETE) {
4203 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4204 << "because offscreen FBO was incomplete.";
4205 return false;
4208 // Clear the target frame buffer.
4210 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4211 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4212 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
4213 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4214 glClearStencil(0);
4215 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4216 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4217 glClearDepth(0);
4218 state_.SetDeviceDepthMask(GL_TRUE);
4219 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4220 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4221 RestoreClearState();
4224 // Destroy the offscreen resolved framebuffers.
4225 if (offscreen_resolved_frame_buffer_.get())
4226 offscreen_resolved_frame_buffer_->Destroy();
4227 if (offscreen_resolved_color_texture_.get())
4228 offscreen_resolved_color_texture_->Destroy();
4229 offscreen_resolved_color_texture_.reset();
4230 offscreen_resolved_frame_buffer_.reset();
4232 return true;
4235 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4236 const void* cmd_data) {
4237 const gles2::cmds::ResizeCHROMIUM& c =
4238 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4239 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4240 return error::kDeferCommandUntilLater;
4242 GLuint width = static_cast<GLuint>(c.width);
4243 GLuint height = static_cast<GLuint>(c.height);
4244 GLfloat scale_factor = c.scale_factor;
4245 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4247 width = std::max(1U, width);
4248 height = std::max(1U, height);
4250 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4251 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4252 // Make sure that we are done drawing to the back buffer before resizing.
4253 glFinish();
4254 #endif
4255 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4256 if (is_offscreen) {
4257 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4258 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4259 << "ResizeOffscreenFrameBuffer failed.";
4260 return error::kLostContext;
4264 if (!resize_callback_.is_null()) {
4265 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4266 DCHECK(context_->IsCurrent(surface_.get()));
4267 if (!context_->IsCurrent(surface_.get())) {
4268 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4269 << "current after resize callback.";
4270 return error::kLostContext;
4274 return error::kNoError;
4277 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4278 if (command_id > kStartPoint && command_id < kNumCommands) {
4279 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4281 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4284 // Decode a command, and call the corresponding GL functions.
4285 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4286 // of commands at once, and is now only used for tests that need to track
4287 // individual commands.
4288 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4289 unsigned int arg_count,
4290 const void* cmd_data) {
4291 return DoCommands(1, cmd_data, arg_count + 1, 0);
4294 // Decode multiple commands, and call the corresponding GL functions.
4295 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4296 // changed by a (malicious) client at any time, so if validation has to happen,
4297 // it should operate on a copy of them.
4298 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4299 // interest of performance in this critical execution loop.
4300 template <bool DebugImpl>
4301 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4302 const void* buffer,
4303 int num_entries,
4304 int* entries_processed) {
4305 commands_to_process_ = num_commands;
4306 error::Error result = error::kNoError;
4307 const CommandBufferEntry* cmd_data =
4308 static_cast<const CommandBufferEntry*>(buffer);
4309 int process_pos = 0;
4310 unsigned int command = 0;
4312 while (process_pos < num_entries && result == error::kNoError &&
4313 commands_to_process_--) {
4314 const unsigned int size = cmd_data->value_header.size;
4315 command = cmd_data->value_header.command;
4317 if (size == 0) {
4318 result = error::kInvalidSize;
4319 break;
4322 if (static_cast<int>(size) + process_pos > num_entries) {
4323 result = error::kOutOfBounds;
4324 break;
4327 if (DebugImpl) {
4328 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4329 GetCommandName(command));
4331 if (log_commands()) {
4332 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4333 << "cmd: " << GetCommandName(command);
4337 const unsigned int arg_count = size - 1;
4338 unsigned int command_index = command - kStartPoint - 1;
4339 if (command_index < arraysize(command_info)) {
4340 const CommandInfo& info = command_info[command_index];
4341 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4342 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4343 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4344 bool doing_gpu_trace = false;
4345 if (DebugImpl && gpu_trace_commands_) {
4346 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4347 doing_gpu_trace = true;
4348 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4349 GetCommandName(command),
4350 kTraceDecoder);
4354 uint32 immediate_data_size = (arg_count - info_arg_count) *
4355 sizeof(CommandBufferEntry); // NOLINT
4357 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4359 if (DebugImpl && doing_gpu_trace)
4360 gpu_tracer_->End(kTraceDecoder);
4362 if (DebugImpl && debug()) {
4363 GLenum error;
4364 while ((error = glGetError()) != GL_NO_ERROR) {
4365 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4366 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4367 << " : " << GetCommandName(command);
4368 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4371 } else {
4372 result = error::kInvalidArguments;
4374 } else {
4375 result = DoCommonCommand(command, arg_count, cmd_data);
4378 if (DebugImpl) {
4379 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4380 GetCommandName(command));
4383 if (result == error::kNoError &&
4384 current_decoder_error_ != error::kNoError) {
4385 result = current_decoder_error_;
4386 current_decoder_error_ = error::kNoError;
4389 if (result != error::kDeferCommandUntilLater) {
4390 process_pos += size;
4391 cmd_data += size;
4395 if (entries_processed)
4396 *entries_processed = process_pos;
4398 if (error::IsError(result)) {
4399 LOG(ERROR) << "Error: " << result << " for Command "
4400 << GetCommandName(command);
4403 return result;
4406 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4407 const void* buffer,
4408 int num_entries,
4409 int* entries_processed) {
4410 if (gpu_debug_commands_) {
4411 return DoCommandsImpl<true>(
4412 num_commands, buffer, num_entries, entries_processed);
4413 } else {
4414 return DoCommandsImpl<false>(
4415 num_commands, buffer, num_entries, entries_processed);
4419 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4420 buffer_manager()->RemoveBuffer(client_id);
4423 void GLES2DecoderImpl::DoFinish() {
4424 glFinish();
4425 ProcessPendingReadPixels(true);
4426 ProcessPendingQueries(true);
4429 void GLES2DecoderImpl::DoFlush() {
4430 glFlush();
4431 ProcessPendingQueries(false);
4434 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4435 GLuint texture_index = texture_unit - GL_TEXTURE0;
4436 if (texture_index >= state_.texture_units.size()) {
4437 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4438 "glActiveTexture", texture_unit, "texture_unit");
4439 return;
4441 state_.active_texture_unit = texture_index;
4442 glActiveTexture(texture_unit);
4445 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4446 Buffer* buffer = NULL;
4447 GLuint service_id = 0;
4448 if (client_id != 0) {
4449 buffer = GetBuffer(client_id);
4450 if (!buffer) {
4451 if (!group_->bind_generates_resource()) {
4452 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4453 "glBindBuffer",
4454 "id not generated by glGenBuffers");
4455 return;
4458 // It's a new id so make a buffer buffer for it.
4459 glGenBuffersARB(1, &service_id);
4460 CreateBuffer(client_id, service_id);
4461 buffer = GetBuffer(client_id);
4464 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4465 if (buffer) {
4466 if (!buffer_manager()->SetTarget(buffer, target)) {
4467 LOCAL_SET_GL_ERROR(
4468 GL_INVALID_OPERATION,
4469 "glBindBuffer", "buffer bound to more than 1 target");
4470 return;
4472 service_id = buffer->service_id();
4474 state_.SetBoundBuffer(target, buffer);
4475 glBindBuffer(target, service_id);
4478 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4479 bool all_draw_buffers) {
4480 Framebuffer* framebuffer =
4481 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4482 if (!all_draw_buffers || !framebuffer) {
4483 return (GLES2Util::GetChannelsForFormat(
4484 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4486 return framebuffer->HasAlphaMRT();
4489 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4490 Framebuffer* framebuffer =
4491 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4492 if (framebuffer) {
4493 return framebuffer->HasDepthAttachment();
4495 if (offscreen_target_frame_buffer_.get()) {
4496 return offscreen_target_depth_format_ != 0;
4498 return back_buffer_has_depth_;
4501 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4502 Framebuffer* framebuffer =
4503 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4504 if (framebuffer) {
4505 return framebuffer->HasStencilAttachment();
4507 if (offscreen_target_frame_buffer_.get()) {
4508 return offscreen_target_stencil_format_ != 0 ||
4509 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4511 return back_buffer_has_stencil_;
4514 void GLES2DecoderImpl::ApplyDirtyState() {
4515 if (framebuffer_state_.clear_state_dirty) {
4516 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4517 state_.SetDeviceColorMask(state_.color_mask_red,
4518 state_.color_mask_green,
4519 state_.color_mask_blue,
4520 state_.color_mask_alpha && have_alpha);
4522 bool have_depth = BoundFramebufferHasDepthAttachment();
4523 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4525 bool have_stencil = BoundFramebufferHasStencilAttachment();
4526 state_.SetDeviceStencilMaskSeparate(
4527 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4528 state_.SetDeviceStencilMaskSeparate(
4529 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4531 state_.SetDeviceCapabilityState(
4532 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4533 state_.SetDeviceCapabilityState(
4534 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4535 framebuffer_state_.clear_state_dirty = false;
4539 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4540 return (offscreen_target_frame_buffer_.get())
4541 ? offscreen_target_frame_buffer_->id()
4542 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4545 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4546 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4547 "context", logger_.GetLogPrefix());
4548 // Restore the Framebuffer first because of bugs in Intel drivers.
4549 // Intel drivers incorrectly clip the viewport settings to
4550 // the size of the current framebuffer object.
4551 RestoreFramebufferBindings();
4552 state_.RestoreState(prev_state);
4555 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4556 GLuint service_id =
4557 framebuffer_state_.bound_draw_framebuffer.get()
4558 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4559 : GetBackbufferServiceId();
4560 if (!features().chromium_framebuffer_multisample) {
4561 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4562 } else {
4563 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4564 service_id = framebuffer_state_.bound_read_framebuffer.get()
4565 ? framebuffer_state_.bound_read_framebuffer->service_id()
4566 : GetBackbufferServiceId();
4567 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4569 OnFboChanged();
4572 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4573 state_.RestoreRenderbufferBindings();
4576 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4577 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4578 if (texture) {
4579 GLenum target = texture->target();
4580 glBindTexture(target, service_id);
4581 glTexParameteri(
4582 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4583 glTexParameteri(
4584 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4585 glTexParameteri(
4586 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4587 glTexParameteri(
4588 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4589 RestoreTextureUnitBindings(state_.active_texture_unit);
4593 void GLES2DecoderImpl::ClearAllAttributes() const {
4594 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4595 // other VAOs.
4596 if (feature_info_->feature_flags().native_vertex_array_object)
4597 glBindVertexArrayOES(0);
4599 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4600 if (i != 0) // Never disable attribute 0
4601 glDisableVertexAttribArray(i);
4602 if (features().angle_instanced_arrays)
4603 glVertexAttribDivisorANGLE(i, 0);
4607 void GLES2DecoderImpl::RestoreAllAttributes() const {
4608 state_.RestoreVertexAttribs();
4611 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4612 state_.SetIgnoreCachedStateForTest(ignore);
4615 void GLES2DecoderImpl::OnFboChanged() const {
4616 if (workarounds().restore_scissor_on_fbo_change)
4617 state_.fbo_binding_for_scissor_workaround_dirty = true;
4619 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4620 GLint bound_fbo_unsigned = -1;
4621 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4622 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4623 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4624 surface_->NotifyWasBound();
4628 // Called after the FBO is checked for completeness.
4629 void GLES2DecoderImpl::OnUseFramebuffer() const {
4630 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4631 state_.fbo_binding_for_scissor_workaround_dirty = false;
4632 // The driver forgets the correct scissor when modifying the FBO binding.
4633 glScissor(state_.scissor_x,
4634 state_.scissor_y,
4635 state_.scissor_width,
4636 state_.scissor_height);
4638 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4639 // it's unclear how this bug works.
4640 glFlush();
4644 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4645 Framebuffer* framebuffer = NULL;
4646 GLuint service_id = 0;
4647 if (client_id != 0) {
4648 framebuffer = GetFramebuffer(client_id);
4649 if (!framebuffer) {
4650 if (!group_->bind_generates_resource()) {
4651 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4652 "glBindFramebuffer",
4653 "id not generated by glGenFramebuffers");
4654 return;
4657 // It's a new id so make a framebuffer framebuffer for it.
4658 glGenFramebuffersEXT(1, &service_id);
4659 CreateFramebuffer(client_id, service_id);
4660 framebuffer = GetFramebuffer(client_id);
4661 } else {
4662 service_id = framebuffer->service_id();
4664 framebuffer->MarkAsValid();
4666 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4668 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4669 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4672 // vmiura: This looks like dup code
4673 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4674 framebuffer_state_.bound_read_framebuffer = framebuffer;
4677 framebuffer_state_.clear_state_dirty = true;
4679 // If we are rendering to the backbuffer get the FBO id for any simulated
4680 // backbuffer.
4681 if (framebuffer == NULL) {
4682 service_id = GetBackbufferServiceId();
4685 glBindFramebufferEXT(target, service_id);
4686 OnFboChanged();
4689 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4690 Renderbuffer* renderbuffer = NULL;
4691 GLuint service_id = 0;
4692 if (client_id != 0) {
4693 renderbuffer = GetRenderbuffer(client_id);
4694 if (!renderbuffer) {
4695 if (!group_->bind_generates_resource()) {
4696 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4697 "glBindRenderbuffer",
4698 "id not generated by glGenRenderbuffers");
4699 return;
4702 // It's a new id so make a renderbuffer for it.
4703 glGenRenderbuffersEXT(1, &service_id);
4704 CreateRenderbuffer(client_id, service_id);
4705 renderbuffer = GetRenderbuffer(client_id);
4706 } else {
4707 service_id = renderbuffer->service_id();
4709 renderbuffer->MarkAsValid();
4711 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4712 state_.bound_renderbuffer = renderbuffer;
4713 state_.bound_renderbuffer_valid = true;
4714 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4717 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4718 TextureRef* texture_ref = NULL;
4719 GLuint service_id = 0;
4720 if (client_id != 0) {
4721 texture_ref = GetTexture(client_id);
4722 if (!texture_ref) {
4723 if (!group_->bind_generates_resource()) {
4724 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4725 "glBindTexture",
4726 "id not generated by glGenTextures");
4727 return;
4730 // It's a new id so make a texture texture for it.
4731 glGenTextures(1, &service_id);
4732 DCHECK_NE(0u, service_id);
4733 CreateTexture(client_id, service_id);
4734 texture_ref = GetTexture(client_id);
4736 } else {
4737 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4740 // Check the texture exists
4741 if (texture_ref) {
4742 Texture* texture = texture_ref->texture();
4743 // Check that we are not trying to bind it to a different target.
4744 if (texture->target() != 0 && texture->target() != target) {
4745 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4746 "glBindTexture",
4747 "texture bound to more than 1 target.");
4748 return;
4750 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4751 if (texture->target() == 0) {
4752 texture_manager()->SetTarget(texture_ref, target);
4754 glBindTexture(target, texture->service_id());
4755 } else {
4756 glBindTexture(target, 0);
4759 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4760 unit.bind_target = target;
4761 switch (target) {
4762 case GL_TEXTURE_2D:
4763 unit.bound_texture_2d = texture_ref;
4764 break;
4765 case GL_TEXTURE_CUBE_MAP:
4766 unit.bound_texture_cube_map = texture_ref;
4767 break;
4768 case GL_TEXTURE_EXTERNAL_OES:
4769 unit.bound_texture_external_oes = texture_ref;
4770 break;
4771 case GL_TEXTURE_RECTANGLE_ARB:
4772 unit.bound_texture_rectangle_arb = texture_ref;
4773 break;
4774 case GL_TEXTURE_3D:
4775 unit.bound_texture_3d = texture_ref;
4776 break;
4777 case GL_TEXTURE_2D_ARRAY:
4778 unit.bound_texture_2d_array = texture_ref;
4779 break;
4780 default:
4781 NOTREACHED(); // Validation should prevent us getting here.
4782 break;
4786 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4787 if (state_.vertex_attrib_manager->Enable(index, false)) {
4788 if (index != 0 ||
4789 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4790 glDisableVertexAttribArray(index);
4792 } else {
4793 LOCAL_SET_GL_ERROR(
4794 GL_INVALID_VALUE,
4795 "glDisableVertexAttribArray", "index out of range");
4799 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4800 GLsizei numAttachments,
4801 const GLenum* attachments) {
4802 if (workarounds().disable_discard_framebuffer)
4803 return;
4805 Framebuffer* framebuffer =
4806 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4808 // Validates the attachments. If one of them fails
4809 // the whole command fails.
4810 for (GLsizei i = 0; i < numAttachments; ++i) {
4811 if ((framebuffer &&
4812 !validators_->attachment.IsValid(attachments[i])) ||
4813 (!framebuffer &&
4814 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4815 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4816 "glDiscardFramebufferEXT", attachments[i], "attachments");
4817 return;
4821 // Marks each one of them as not cleared
4822 for (GLsizei i = 0; i < numAttachments; ++i) {
4823 if (framebuffer) {
4824 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4825 texture_manager(),
4826 attachments[i],
4827 false);
4828 } else {
4829 switch (attachments[i]) {
4830 case GL_COLOR_EXT:
4831 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4832 break;
4833 case GL_DEPTH_EXT:
4834 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4835 case GL_STENCIL_EXT:
4836 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4837 break;
4838 default:
4839 NOTREACHED();
4840 break;
4845 // If the default framebuffer is bound but we are still rendering to an
4846 // FBO, translate attachment names that refer to default framebuffer
4847 // channels to corresponding framebuffer attachments.
4848 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4849 for (GLsizei i = 0; i < numAttachments; ++i) {
4850 GLenum attachment = attachments[i];
4851 if (!framebuffer && GetBackbufferServiceId()) {
4852 switch (attachment) {
4853 case GL_COLOR_EXT:
4854 attachment = GL_COLOR_ATTACHMENT0;
4855 break;
4856 case GL_DEPTH_EXT:
4857 attachment = GL_DEPTH_ATTACHMENT;
4858 break;
4859 case GL_STENCIL_EXT:
4860 attachment = GL_STENCIL_ATTACHMENT;
4861 break;
4862 default:
4863 NOTREACHED();
4864 return;
4867 translated_attachments[i] = attachment;
4870 ScopedRenderTo do_render(framebuffer);
4871 if (feature_info_->gl_version_info().is_es3) {
4872 glInvalidateFramebuffer(
4873 target, numAttachments, translated_attachments.get());
4874 } else {
4875 glDiscardFramebufferEXT(
4876 target, numAttachments, translated_attachments.get());
4880 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4881 if (state_.vertex_attrib_manager->Enable(index, true)) {
4882 glEnableVertexAttribArray(index);
4883 } else {
4884 LOCAL_SET_GL_ERROR(
4885 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4889 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4890 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4891 &state_, target);
4892 if (!texture_ref ||
4893 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4894 LOCAL_SET_GL_ERROR(
4895 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4896 return;
4899 if (target == GL_TEXTURE_CUBE_MAP) {
4900 for (int i = 0; i < 6; ++i) {
4901 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4902 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4903 LOCAL_SET_GL_ERROR(
4904 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4905 return;
4908 } else {
4909 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4910 LOCAL_SET_GL_ERROR(
4911 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4912 return;
4916 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4917 // Workaround for Mac driver bug. In the large scheme of things setting
4918 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4919 // hit so there's probably no need to make this conditional. The bug appears
4920 // to be that if the filtering mode is set to something that doesn't require
4921 // mipmaps for rendering, or is never set to something other than the default,
4922 // then glGenerateMipmap misbehaves.
4923 if (workarounds().set_texture_filter_before_generating_mipmap) {
4924 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4926 glGenerateMipmapEXT(target);
4927 if (workarounds().set_texture_filter_before_generating_mipmap) {
4928 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4929 texture_ref->texture()->min_filter());
4931 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4932 if (error == GL_NO_ERROR) {
4933 texture_manager()->MarkMipmapsGenerated(texture_ref);
4937 bool GLES2DecoderImpl::GetHelper(
4938 GLenum pname, GLint* params, GLsizei* num_written) {
4939 DCHECK(num_written);
4940 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4941 switch (pname) {
4942 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4943 *num_written = 1;
4944 // Return the GL implementation's preferred format and (see below type)
4945 // if we have the GL extension that exposes this. This allows the GPU
4946 // client to use the implementation's preferred format for glReadPixels
4947 // for optimisation.
4949 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4950 // case when requested on integer/floating point buffers but which is
4951 // acceptable on GLES2 and with the GL_OES_read_format extension.
4953 // Therefore if an error occurs we swallow the error and use the
4954 // internal implementation.
4955 if (params) {
4956 if (context_->HasExtension("GL_OES_read_format")) {
4957 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4958 GetErrorState());
4959 glGetIntegerv(pname, params);
4960 if (glGetError() == GL_NO_ERROR)
4961 return true;
4963 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4964 GetBoundReadFrameBufferInternalFormat());
4966 return true;
4967 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4968 *num_written = 1;
4969 if (params) {
4970 if (context_->HasExtension("GL_OES_read_format")) {
4971 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4972 GetErrorState());
4973 glGetIntegerv(pname, params);
4974 if (glGetError() == GL_NO_ERROR)
4975 return true;
4977 *params = GLES2Util::GetPreferredGLReadPixelsType(
4978 GetBoundReadFrameBufferInternalFormat(),
4979 GetBoundReadFrameBufferTextureType());
4981 return true;
4982 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4983 *num_written = 1;
4984 if (params) {
4985 *params = group_->max_fragment_uniform_vectors();
4987 return true;
4988 case GL_MAX_VARYING_VECTORS:
4989 *num_written = 1;
4990 if (params) {
4991 *params = group_->max_varying_vectors();
4993 return true;
4994 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4995 *num_written = 1;
4996 if (params) {
4997 *params = group_->max_vertex_uniform_vectors();
4999 return true;
5002 if (unsafe_es3_apis_enabled()) {
5003 switch (pname) {
5004 case GL_MAX_VARYING_COMPONENTS: {
5005 if (feature_info_->gl_version_info().is_es) {
5006 // We can just delegate this query to the driver.
5007 return false;
5010 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5011 // OpenGL core profile, so for simplicity, just compute it
5012 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5013 // configurations.
5014 GLint max_varying_vectors = 0;
5015 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5016 *num_written = 1;
5017 if (params) {
5018 *params = max_varying_vectors * 4;
5020 return true;
5022 case GL_READ_BUFFER:
5023 *num_written = 1;
5024 if (params) {
5025 Framebuffer* framebuffer =
5026 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5027 GLenum read_buffer;
5028 if (framebuffer) {
5029 read_buffer = framebuffer->read_buffer();
5030 } else {
5031 read_buffer = back_buffer_read_buffer_;
5033 *params = static_cast<GLint>(read_buffer);
5035 return true;
5038 switch (pname) {
5039 case GL_MAX_VIEWPORT_DIMS:
5040 if (offscreen_target_frame_buffer_.get()) {
5041 *num_written = 2;
5042 if (params) {
5043 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5044 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5046 return true;
5048 return false;
5049 case GL_MAX_SAMPLES:
5050 *num_written = 1;
5051 if (params) {
5052 params[0] = renderbuffer_manager()->max_samples();
5054 return true;
5055 case GL_MAX_RENDERBUFFER_SIZE:
5056 *num_written = 1;
5057 if (params) {
5058 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5060 return true;
5061 case GL_MAX_TEXTURE_SIZE:
5062 *num_written = 1;
5063 if (params) {
5064 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5066 return true;
5067 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5068 *num_written = 1;
5069 if (params) {
5070 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5072 return true;
5073 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5074 *num_written = 1;
5075 if (params) {
5076 params[0] = group_->max_color_attachments();
5078 return true;
5079 case GL_MAX_DRAW_BUFFERS_ARB:
5080 *num_written = 1;
5081 if (params) {
5082 params[0] = group_->max_draw_buffers();
5084 return true;
5085 case GL_ALPHA_BITS:
5086 *num_written = 1;
5087 if (params) {
5088 GLint v = 0;
5089 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5090 Framebuffer* framebuffer =
5091 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5092 if (framebuffer) {
5093 glGetFramebufferAttachmentParameterivEXT(
5094 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5095 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5096 } else {
5097 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
5099 } else {
5100 glGetIntegerv(GL_ALPHA_BITS, &v);
5102 params[0] =
5103 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
5105 return true;
5106 case GL_DEPTH_BITS:
5107 *num_written = 1;
5108 if (params) {
5109 GLint v = 0;
5110 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5111 Framebuffer* framebuffer =
5112 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5113 if (framebuffer) {
5114 glGetFramebufferAttachmentParameterivEXT(
5115 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5116 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5117 } else {
5118 v = (back_buffer_has_depth_ ? 24 : 0);
5120 } else {
5121 glGetIntegerv(GL_DEPTH_BITS, &v);
5123 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5125 return true;
5126 case GL_RED_BITS:
5127 case GL_GREEN_BITS:
5128 case GL_BLUE_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 GLenum framebuffer_enum = 0;
5137 switch (pname) {
5138 case GL_RED_BITS:
5139 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5140 break;
5141 case GL_GREEN_BITS:
5142 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5143 break;
5144 case GL_BLUE_BITS:
5145 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5146 break;
5148 glGetFramebufferAttachmentParameterivEXT(
5149 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5150 } else {
5151 v = 8;
5153 } else {
5154 glGetIntegerv(pname, &v);
5156 params[0] = v;
5158 return true;
5159 case GL_STENCIL_BITS:
5160 *num_written = 1;
5161 if (params) {
5162 GLint v = 0;
5163 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5164 Framebuffer* framebuffer =
5165 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5166 if (framebuffer) {
5167 glGetFramebufferAttachmentParameterivEXT(
5168 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5169 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5170 } else {
5171 v = (back_buffer_has_stencil_ ? 8 : 0);
5173 } else {
5174 glGetIntegerv(GL_STENCIL_BITS, &v);
5176 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5178 return true;
5179 case GL_COMPRESSED_TEXTURE_FORMATS:
5180 *num_written = validators_->compressed_texture_format.GetValues().size();
5181 if (params) {
5182 for (GLint ii = 0; ii < *num_written; ++ii) {
5183 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5186 return true;
5187 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5188 *num_written = 1;
5189 if (params) {
5190 *params = validators_->compressed_texture_format.GetValues().size();
5192 return true;
5193 case GL_NUM_SHADER_BINARY_FORMATS:
5194 *num_written = 1;
5195 if (params) {
5196 *params = validators_->shader_binary_format.GetValues().size();
5198 return true;
5199 case GL_SHADER_BINARY_FORMATS:
5200 *num_written = validators_->shader_binary_format.GetValues().size();
5201 if (params) {
5202 for (GLint ii = 0; ii < *num_written; ++ii) {
5203 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5206 return true;
5207 case GL_SHADER_COMPILER:
5208 *num_written = 1;
5209 if (params) {
5210 *params = GL_TRUE;
5212 return true;
5213 case GL_ARRAY_BUFFER_BINDING:
5214 *num_written = 1;
5215 if (params) {
5216 *params = GetClientId(
5217 buffer_manager(), state_.bound_array_buffer.get());
5219 return true;
5220 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5221 *num_written = 1;
5222 if (params) {
5223 *params = GetClientId(
5224 buffer_manager(),
5225 state_.vertex_attrib_manager->element_array_buffer());
5227 return true;
5228 case GL_COPY_READ_BUFFER_BINDING:
5229 *num_written = 1;
5230 if (params) {
5231 *params = GetClientId(
5232 buffer_manager(), state_.bound_copy_read_buffer.get());
5234 return true;
5235 case GL_COPY_WRITE_BUFFER_BINDING:
5236 *num_written = 1;
5237 if (params) {
5238 *params = GetClientId(
5239 buffer_manager(), state_.bound_copy_write_buffer.get());
5241 return true;
5242 case GL_PIXEL_PACK_BUFFER_BINDING:
5243 *num_written = 1;
5244 if (params) {
5245 *params = GetClientId(
5246 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5248 return true;
5249 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5250 *num_written = 1;
5251 if (params) {
5252 *params = GetClientId(
5253 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5255 return true;
5256 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5257 *num_written = 1;
5258 if (params) {
5259 *params = GetClientId(
5260 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5262 return true;
5263 case GL_UNIFORM_BUFFER_BINDING:
5264 *num_written = 1;
5265 if (params) {
5266 *params = GetClientId(
5267 buffer_manager(), state_.bound_uniform_buffer.get());
5269 return true;
5270 case GL_FRAMEBUFFER_BINDING:
5271 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5272 *num_written = 1;
5273 if (params) {
5274 *params = GetClientId(
5275 framebuffer_manager(),
5276 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5278 return true;
5279 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5280 *num_written = 1;
5281 if (params) {
5282 *params = GetClientId(
5283 framebuffer_manager(),
5284 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5286 return true;
5287 case GL_RENDERBUFFER_BINDING:
5288 *num_written = 1;
5289 if (params) {
5290 Renderbuffer* renderbuffer =
5291 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5292 if (renderbuffer) {
5293 *params = renderbuffer->client_id();
5294 } else {
5295 *params = 0;
5298 return true;
5299 case GL_CURRENT_PROGRAM:
5300 *num_written = 1;
5301 if (params) {
5302 *params = GetClientId(program_manager(), state_.current_program.get());
5304 return true;
5305 case GL_VERTEX_ARRAY_BINDING_OES:
5306 *num_written = 1;
5307 if (params) {
5308 if (state_.vertex_attrib_manager.get() !=
5309 state_.default_vertex_attrib_manager.get()) {
5310 GLuint client_id = 0;
5311 vertex_array_manager_->GetClientId(
5312 state_.vertex_attrib_manager->service_id(), &client_id);
5313 *params = client_id;
5314 } else {
5315 *params = 0;
5318 return true;
5319 case GL_TEXTURE_BINDING_2D:
5320 *num_written = 1;
5321 if (params) {
5322 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5323 if (unit.bound_texture_2d.get()) {
5324 *params = unit.bound_texture_2d->client_id();
5325 } else {
5326 *params = 0;
5329 return true;
5330 case GL_TEXTURE_BINDING_CUBE_MAP:
5331 *num_written = 1;
5332 if (params) {
5333 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5334 if (unit.bound_texture_cube_map.get()) {
5335 *params = unit.bound_texture_cube_map->client_id();
5336 } else {
5337 *params = 0;
5340 return true;
5341 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5342 *num_written = 1;
5343 if (params) {
5344 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5345 if (unit.bound_texture_external_oes.get()) {
5346 *params = unit.bound_texture_external_oes->client_id();
5347 } else {
5348 *params = 0;
5351 return true;
5352 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5353 *num_written = 1;
5354 if (params) {
5355 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5356 if (unit.bound_texture_rectangle_arb.get()) {
5357 *params = unit.bound_texture_rectangle_arb->client_id();
5358 } else {
5359 *params = 0;
5362 return true;
5363 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5364 *num_written = 1;
5365 if (params) {
5366 params[0] = group_->bind_generates_resource() ? 1 : 0;
5368 return true;
5369 default:
5370 if (pname >= GL_DRAW_BUFFER0_ARB &&
5371 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5372 *num_written = 1;
5373 if (params) {
5374 Framebuffer* framebuffer =
5375 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5376 if (framebuffer) {
5377 params[0] = framebuffer->GetDrawBuffer(pname);
5378 } else { // backbuffer
5379 if (pname == GL_DRAW_BUFFER0_ARB)
5380 params[0] = group_->draw_buffer();
5381 else
5382 params[0] = GL_NONE;
5385 return true;
5387 *num_written = util_.GLGetNumValuesReturned(pname);
5388 return false;
5392 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5393 GLenum pname, GLsizei* num_values) {
5394 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5395 return true;
5397 return GetHelper(pname, NULL, num_values);
5400 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5401 if (GL_MAX_SAMPLES == pname &&
5402 features().use_img_for_multisampled_render_to_texture) {
5403 return GL_MAX_SAMPLES_IMG;
5405 return pname;
5408 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5409 DCHECK(params);
5410 GLsizei num_written = 0;
5411 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5412 scoped_ptr<GLint[]> values(new GLint[num_written]);
5413 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5414 GetHelper(pname, values.get(), &num_written);
5416 for (GLsizei ii = 0; ii < num_written; ++ii) {
5417 params[ii] = static_cast<GLboolean>(values[ii]);
5419 } else {
5420 pname = AdjustGetPname(pname);
5421 glGetBooleanv(pname, params);
5425 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5426 DCHECK(params);
5427 GLsizei num_written = 0;
5428 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5429 if (GetHelper(pname, NULL, &num_written)) {
5430 scoped_ptr<GLint[]> values(new GLint[num_written]);
5431 GetHelper(pname, values.get(), &num_written);
5432 for (GLsizei ii = 0; ii < num_written; ++ii) {
5433 params[ii] = static_cast<GLfloat>(values[ii]);
5435 } else {
5436 pname = AdjustGetPname(pname);
5437 glGetFloatv(pname, params);
5442 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5443 DCHECK(params);
5444 if (unsafe_es3_apis_enabled()) {
5445 switch (pname) {
5446 case GL_MAX_ELEMENT_INDEX: {
5447 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5448 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5449 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5450 } else {
5451 // Assume that desktop GL implementations can generally support
5452 // 32-bit indices.
5453 if (params) {
5454 *params = std::numeric_limits<unsigned int>::max();
5457 return;
5461 pname = AdjustGetPname(pname);
5462 glGetInteger64v(pname, params);
5465 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5466 DCHECK(params);
5467 GLsizei num_written;
5468 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5469 !GetHelper(pname, params, &num_written)) {
5470 pname = AdjustGetPname(pname);
5471 glGetIntegerv(pname, params);
5475 void GLES2DecoderImpl::DoGetProgramiv(
5476 GLuint program_id, GLenum pname, GLint* params) {
5477 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5478 if (!program) {
5479 return;
5481 program->GetProgramiv(pname, params);
5484 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5485 GLenum target, GLenum pname, GLint64* params) {
5486 // Just delegate it. Some validation is actually done before this.
5487 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5488 &state_, target, pname, params);
5491 void GLES2DecoderImpl::DoGetBufferParameteriv(
5492 GLenum target, GLenum pname, GLint* params) {
5493 // Just delegate it. Some validation is actually done before this.
5494 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5495 &state_, target, pname, params);
5498 void GLES2DecoderImpl::DoBindAttribLocation(
5499 GLuint program_id, GLuint index, const char* name) {
5500 if (!StringIsValidForGLES(name)) {
5501 LOCAL_SET_GL_ERROR(
5502 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5503 return;
5505 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5506 LOCAL_SET_GL_ERROR(
5507 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5508 return;
5510 if (index >= group_->max_vertex_attribs()) {
5511 LOCAL_SET_GL_ERROR(
5512 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5513 return;
5515 Program* program = GetProgramInfoNotShader(
5516 program_id, "glBindAttribLocation");
5517 if (!program) {
5518 return;
5520 // At this point, the program's shaders may not be translated yet,
5521 // therefore, we may not find the hashed attribute name.
5522 // glBindAttribLocation call with original name is useless.
5523 // So instead, we should simply cache the binding, and then call
5524 // Program::ExecuteBindAttribLocationCalls() right before link.
5525 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5526 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5527 glBindAttribLocation(program->service_id(), index, name);
5530 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5531 uint32 immediate_data_size,
5532 const void* cmd_data) {
5533 const gles2::cmds::BindAttribLocationBucket& c =
5534 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5535 GLuint program = static_cast<GLuint>(c.program);
5536 GLuint index = static_cast<GLuint>(c.index);
5537 Bucket* bucket = GetBucket(c.name_bucket_id);
5538 if (!bucket || bucket->size() == 0) {
5539 return error::kInvalidArguments;
5541 std::string name_str;
5542 if (!bucket->GetAsString(&name_str)) {
5543 return error::kInvalidArguments;
5545 DoBindAttribLocation(program, index, name_str.c_str());
5546 return error::kNoError;
5549 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5550 GLuint program_id, GLint location, const char* name) {
5551 if (!StringIsValidForGLES(name)) {
5552 LOCAL_SET_GL_ERROR(
5553 GL_INVALID_VALUE,
5554 "glBindUniformLocationCHROMIUM", "Invalid character");
5555 return;
5557 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5558 LOCAL_SET_GL_ERROR(
5559 GL_INVALID_OPERATION,
5560 "glBindUniformLocationCHROMIUM", "reserved prefix");
5561 return;
5563 if (location < 0 || static_cast<uint32>(location) >=
5564 (group_->max_fragment_uniform_vectors() +
5565 group_->max_vertex_uniform_vectors()) * 4) {
5566 LOCAL_SET_GL_ERROR(
5567 GL_INVALID_VALUE,
5568 "glBindUniformLocationCHROMIUM", "location out of range");
5569 return;
5571 Program* program = GetProgramInfoNotShader(
5572 program_id, "glBindUniformLocationCHROMIUM");
5573 if (!program) {
5574 return;
5576 if (!program->SetUniformLocationBinding(name, location)) {
5577 LOCAL_SET_GL_ERROR(
5578 GL_INVALID_VALUE,
5579 "glBindUniformLocationCHROMIUM", "location out of range");
5583 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5584 uint32 immediate_data_size,
5585 const void* cmd_data) {
5586 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5587 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5588 cmd_data);
5589 GLuint program = static_cast<GLuint>(c.program);
5590 GLint location = static_cast<GLint>(c.location);
5591 Bucket* bucket = GetBucket(c.name_bucket_id);
5592 if (!bucket || bucket->size() == 0) {
5593 return error::kInvalidArguments;
5595 std::string name_str;
5596 if (!bucket->GetAsString(&name_str)) {
5597 return error::kInvalidArguments;
5599 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5600 return error::kNoError;
5603 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5604 const void* cmd_data) {
5605 const gles2::cmds::DeleteShader& c =
5606 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5607 GLuint client_id = c.shader;
5608 if (client_id) {
5609 Shader* shader = GetShader(client_id);
5610 if (shader) {
5611 if (!shader->IsDeleted()) {
5612 shader_manager()->Delete(shader);
5614 } else {
5615 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5618 return error::kNoError;
5621 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5622 const void* cmd_data) {
5623 const gles2::cmds::DeleteProgram& c =
5624 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5625 GLuint client_id = c.program;
5626 if (client_id) {
5627 Program* program = GetProgram(client_id);
5628 if (program) {
5629 if (!program->IsDeleted()) {
5630 program_manager()->MarkAsDeleted(shader_manager(), program);
5632 } else {
5633 LOCAL_SET_GL_ERROR(
5634 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5637 return error::kNoError;
5640 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5641 DCHECK(!ShouldDeferDraws());
5642 if (CheckBoundFramebuffersValid("glClear")) {
5643 ApplyDirtyState();
5644 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5645 if (workarounds().gl_clear_broken) {
5646 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5647 GetErrorState());
5648 if (!BoundFramebufferHasDepthAttachment())
5649 mask &= ~GL_DEPTH_BUFFER_BIT;
5650 if (!BoundFramebufferHasStencilAttachment())
5651 mask &= ~GL_STENCIL_BUFFER_BIT;
5652 clear_framebuffer_blit_->ClearFramebuffer(
5653 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5654 state_.color_clear_green, state_.color_clear_blue,
5655 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5656 return error::kNoError;
5658 glClear(mask);
5660 return error::kNoError;
5663 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5664 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5665 GLuint client_renderbuffer_id) {
5666 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5667 if (!framebuffer) {
5668 LOCAL_SET_GL_ERROR(
5669 GL_INVALID_OPERATION,
5670 "glFramebufferRenderbuffer", "no framebuffer bound");
5671 return;
5673 GLuint service_id = 0;
5674 Renderbuffer* renderbuffer = NULL;
5675 if (client_renderbuffer_id) {
5676 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5677 if (!renderbuffer) {
5678 LOCAL_SET_GL_ERROR(
5679 GL_INVALID_OPERATION,
5680 "glFramebufferRenderbuffer", "unknown renderbuffer");
5681 return;
5683 service_id = renderbuffer->service_id();
5685 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5686 glFramebufferRenderbufferEXT(
5687 target, attachment, renderbuffertarget, service_id);
5688 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5689 if (error == GL_NO_ERROR) {
5690 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5692 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5693 framebuffer_state_.clear_state_dirty = true;
5695 OnFboChanged();
5698 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5699 if (SetCapabilityState(cap, false)) {
5700 glDisable(cap);
5704 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5705 if (SetCapabilityState(cap, true)) {
5706 glEnable(cap);
5710 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5711 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5712 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5713 glDepthRange(znear, zfar);
5716 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5717 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5718 state_.sample_coverage_invert = (invert != 0);
5719 glSampleCoverage(state_.sample_coverage_value, invert);
5722 // Assumes framebuffer is complete.
5723 void GLES2DecoderImpl::ClearUnclearedAttachments(
5724 GLenum target, Framebuffer* framebuffer) {
5725 if (target == GL_READ_FRAMEBUFFER_EXT) {
5726 // bind this to the DRAW point, clear then bind back to READ
5727 // TODO(gman): I don't think there is any guarantee that an FBO that
5728 // is complete on the READ attachment will be complete as a DRAW
5729 // attachment.
5730 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5731 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5733 GLbitfield clear_bits = 0;
5734 if (framebuffer->HasUnclearedColorAttachments()) {
5735 glClearColor(
5736 0.0f, 0.0f, 0.0f,
5737 (GLES2Util::GetChannelsForFormat(
5738 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5739 1.0f);
5740 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5741 clear_bits |= GL_COLOR_BUFFER_BIT;
5742 if (feature_info_->feature_flags().ext_draw_buffers)
5743 framebuffer->PrepareDrawBuffersForClear();
5746 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5747 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5748 glClearStencil(0);
5749 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5750 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5751 clear_bits |= GL_STENCIL_BUFFER_BIT;
5754 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5755 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5756 glClearDepth(1.0f);
5757 state_.SetDeviceDepthMask(GL_TRUE);
5758 clear_bits |= GL_DEPTH_BUFFER_BIT;
5761 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5762 glClear(clear_bits);
5764 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5765 feature_info_->feature_flags().ext_draw_buffers)
5766 framebuffer->RestoreDrawBuffersAfterClear();
5768 framebuffer_manager()->MarkAttachmentsAsCleared(
5769 framebuffer, renderbuffer_manager(), texture_manager());
5771 RestoreClearState();
5773 if (target == GL_READ_FRAMEBUFFER_EXT) {
5774 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5775 Framebuffer* draw_framebuffer =
5776 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5777 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5778 GetBackbufferServiceId();
5779 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5783 void GLES2DecoderImpl::RestoreClearState() {
5784 framebuffer_state_.clear_state_dirty = true;
5785 glClearColor(
5786 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5787 state_.color_clear_alpha);
5788 glClearStencil(state_.stencil_clear);
5789 glClearDepth(state_.depth_clear);
5790 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5791 state_.enable_flags.scissor_test);
5792 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
5793 state_.scissor_height);
5796 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5797 Framebuffer* framebuffer =
5798 GetFramebufferInfoForTarget(target);
5799 if (!framebuffer) {
5800 return GL_FRAMEBUFFER_COMPLETE;
5802 GLenum completeness = framebuffer->IsPossiblyComplete();
5803 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5804 return completeness;
5806 return framebuffer->GetStatus(texture_manager(), target);
5809 void GLES2DecoderImpl::DoFramebufferTexture2D(
5810 GLenum target, GLenum attachment, GLenum textarget,
5811 GLuint client_texture_id, GLint level) {
5812 DoFramebufferTexture2DCommon(
5813 "glFramebufferTexture2D", target, attachment,
5814 textarget, client_texture_id, level, 0);
5817 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5818 GLenum target, GLenum attachment, GLenum textarget,
5819 GLuint client_texture_id, GLint level, GLsizei samples) {
5820 DoFramebufferTexture2DCommon(
5821 "glFramebufferTexture2DMultisample", target, attachment,
5822 textarget, client_texture_id, level, samples);
5825 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5826 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5827 GLuint client_texture_id, GLint level, GLsizei samples) {
5828 if (samples > renderbuffer_manager()->max_samples()) {
5829 LOCAL_SET_GL_ERROR(
5830 GL_INVALID_VALUE,
5831 "glFramebufferTexture2DMultisample", "samples too large");
5832 return;
5834 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5835 if (!framebuffer) {
5836 LOCAL_SET_GL_ERROR(
5837 GL_INVALID_OPERATION,
5838 name, "no framebuffer bound.");
5839 return;
5841 GLuint service_id = 0;
5842 TextureRef* texture_ref = NULL;
5843 if (client_texture_id) {
5844 texture_ref = GetTexture(client_texture_id);
5845 if (!texture_ref) {
5846 LOCAL_SET_GL_ERROR(
5847 GL_INVALID_OPERATION,
5848 name, "unknown texture_ref");
5849 return;
5851 service_id = texture_ref->service_id();
5854 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5855 LOCAL_SET_GL_ERROR(
5856 GL_INVALID_VALUE,
5857 name, "level out of range");
5858 return;
5861 if (texture_ref)
5862 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5864 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5865 if (0 == samples) {
5866 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5867 } else {
5868 if (features().use_img_for_multisampled_render_to_texture) {
5869 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5870 service_id, level, samples);
5871 } else {
5872 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5873 service_id, level, samples);
5876 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5877 if (error == GL_NO_ERROR) {
5878 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5879 samples);
5881 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5882 framebuffer_state_.clear_state_dirty = true;
5885 if (texture_ref)
5886 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5888 OnFboChanged();
5891 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5892 GLenum target, GLenum attachment, GLuint client_texture_id,
5893 GLint level, GLint layer) {
5894 // TODO(zmo): Unsafe ES3 API, missing states update.
5895 GLuint service_id = 0;
5896 TextureRef* texture_ref = NULL;
5897 if (client_texture_id) {
5898 texture_ref = GetTexture(client_texture_id);
5899 if (!texture_ref) {
5900 LOCAL_SET_GL_ERROR(
5901 GL_INVALID_OPERATION,
5902 "glFramebufferTextureLayer", "unknown texture_ref");
5903 return;
5905 service_id = texture_ref->service_id();
5907 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5910 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5911 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5912 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5913 if (!framebuffer) {
5914 LOCAL_SET_GL_ERROR(
5915 GL_INVALID_OPERATION,
5916 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5917 return;
5919 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5920 const Framebuffer::Attachment* attachment_object =
5921 framebuffer->GetAttachment(attachment);
5922 *params = attachment_object ? attachment_object->object_name() : 0;
5923 } else {
5924 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5925 features().use_img_for_multisampled_render_to_texture) {
5926 pname = GL_TEXTURE_SAMPLES_IMG;
5928 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5932 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5933 GLenum target, GLenum pname, GLint* params) {
5934 Renderbuffer* renderbuffer =
5935 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5936 if (!renderbuffer) {
5937 LOCAL_SET_GL_ERROR(
5938 GL_INVALID_OPERATION,
5939 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5940 return;
5943 EnsureRenderbufferBound();
5944 switch (pname) {
5945 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5946 *params = renderbuffer->internal_format();
5947 break;
5948 case GL_RENDERBUFFER_WIDTH:
5949 *params = renderbuffer->width();
5950 break;
5951 case GL_RENDERBUFFER_HEIGHT:
5952 *params = renderbuffer->height();
5953 break;
5954 case GL_RENDERBUFFER_SAMPLES_EXT:
5955 if (features().use_img_for_multisampled_render_to_texture) {
5956 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5957 params);
5958 } else {
5959 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5960 params);
5962 default:
5963 glGetRenderbufferParameterivEXT(target, pname, params);
5964 break;
5968 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5969 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5970 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5971 GLbitfield mask, GLenum filter) {
5972 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5974 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5975 return;
5978 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5979 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5980 BlitFramebufferHelper(
5981 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5982 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5983 state_.enable_flags.scissor_test);
5986 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5987 if (!state_.bound_renderbuffer_valid) {
5988 state_.bound_renderbuffer_valid = true;
5989 glBindRenderbufferEXT(GL_RENDERBUFFER,
5990 state_.bound_renderbuffer.get()
5991 ? state_.bound_renderbuffer->service_id()
5992 : 0);
5996 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5997 const FeatureInfo* feature_info,
5998 GLenum target,
5999 GLsizei samples,
6000 GLenum internal_format,
6001 GLsizei width,
6002 GLsizei height) {
6003 // TODO(sievers): This could be resolved at the GL binding level, but the
6004 // binding process is currently a bit too 'brute force'.
6005 if (feature_info->gl_version_info().is_angle) {
6006 glRenderbufferStorageMultisampleANGLE(
6007 target, samples, internal_format, width, height);
6008 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6009 glRenderbufferStorageMultisample(
6010 target, samples, internal_format, width, height);
6011 } else {
6012 glRenderbufferStorageMultisampleEXT(
6013 target, samples, internal_format, width, height);
6017 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6018 GLint srcY0,
6019 GLint srcX1,
6020 GLint srcY1,
6021 GLint dstX0,
6022 GLint dstY0,
6023 GLint dstX1,
6024 GLint dstY1,
6025 GLbitfield mask,
6026 GLenum filter) {
6027 // TODO(sievers): This could be resolved at the GL binding level, but the
6028 // binding process is currently a bit too 'brute force'.
6029 if (feature_info_->gl_version_info().is_angle) {
6030 glBlitFramebufferANGLE(
6031 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6032 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6033 glBlitFramebuffer(
6034 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6035 } else {
6036 glBlitFramebufferEXT(
6037 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6041 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6042 GLsizei samples,
6043 GLenum internalformat,
6044 GLsizei width,
6045 GLsizei height) {
6046 if (samples > renderbuffer_manager()->max_samples()) {
6047 LOCAL_SET_GL_ERROR(
6048 GL_INVALID_VALUE,
6049 "glRenderbufferStorageMultisample", "samples too large");
6050 return false;
6053 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6054 height > renderbuffer_manager()->max_renderbuffer_size()) {
6055 LOCAL_SET_GL_ERROR(
6056 GL_INVALID_VALUE,
6057 "glRenderbufferStorageMultisample", "dimensions too large");
6058 return false;
6061 uint32 estimated_size = 0;
6062 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6063 width, height, samples, internalformat, &estimated_size)) {
6064 LOCAL_SET_GL_ERROR(
6065 GL_OUT_OF_MEMORY,
6066 "glRenderbufferStorageMultisample", "dimensions too large");
6067 return false;
6070 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6071 LOCAL_SET_GL_ERROR(
6072 GL_OUT_OF_MEMORY,
6073 "glRenderbufferStorageMultisample", "out of memory");
6074 return false;
6077 return true;
6080 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6081 GLenum target, GLsizei samples, GLenum internalformat,
6082 GLsizei width, GLsizei height) {
6083 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6084 if (!renderbuffer) {
6085 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6086 "glRenderbufferStorageMultisampleCHROMIUM",
6087 "no renderbuffer bound");
6088 return;
6091 if (!ValidateRenderbufferStorageMultisample(
6092 samples, internalformat, width, height)) {
6093 return;
6096 EnsureRenderbufferBound();
6097 GLenum impl_format =
6098 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6099 internalformat);
6100 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6101 "glRenderbufferStorageMultisampleCHROMIUM");
6102 RenderbufferStorageMultisampleHelper(
6103 feature_info_.get(), target, samples, impl_format, width, height);
6104 GLenum error =
6105 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6106 if (error == GL_NO_ERROR) {
6107 if (workarounds().validate_multisample_buffer_allocation) {
6108 if (!VerifyMultisampleRenderbufferIntegrity(
6109 renderbuffer->service_id(), impl_format)) {
6110 LOCAL_SET_GL_ERROR(
6111 GL_OUT_OF_MEMORY,
6112 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6113 return;
6117 // TODO(gman): If renderbuffers tracked which framebuffers they were
6118 // attached to we could just mark those framebuffers as not complete.
6119 framebuffer_manager()->IncFramebufferStateChangeCount();
6120 renderbuffer_manager()->SetInfo(
6121 renderbuffer, samples, internalformat, width, height);
6125 // This is the handler for multisampled_render_to_texture extensions.
6126 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6127 GLenum target, GLsizei samples, GLenum internalformat,
6128 GLsizei width, GLsizei height) {
6129 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6130 if (!renderbuffer) {
6131 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6132 "glRenderbufferStorageMultisampleEXT",
6133 "no renderbuffer bound");
6134 return;
6137 if (!ValidateRenderbufferStorageMultisample(
6138 samples, internalformat, width, height)) {
6139 return;
6142 EnsureRenderbufferBound();
6143 GLenum impl_format =
6144 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6145 internalformat);
6146 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6147 if (features().use_img_for_multisampled_render_to_texture) {
6148 glRenderbufferStorageMultisampleIMG(
6149 target, samples, impl_format, width, height);
6150 } else {
6151 glRenderbufferStorageMultisampleEXT(
6152 target, samples, impl_format, width, height);
6154 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6155 if (error == GL_NO_ERROR) {
6156 // TODO(gman): If renderbuffers tracked which framebuffers they were
6157 // attached to we could just mark those framebuffers as not complete.
6158 framebuffer_manager()->IncFramebufferStateChangeCount();
6159 renderbuffer_manager()->SetInfo(
6160 renderbuffer, samples, internalformat, width, height);
6164 // This function validates the allocation of a multisampled renderbuffer
6165 // by clearing it to a key color, blitting the contents to a texture, and
6166 // reading back the color to ensure it matches the key.
6167 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6168 GLuint renderbuffer, GLenum format) {
6170 // Only validate color buffers.
6171 // These formats have been selected because they are very common or are known
6172 // to be used by the WebGL backbuffer. If problems are observed with other
6173 // color formats they can be added here.
6174 switch (format) {
6175 case GL_RGB:
6176 case GL_RGB8:
6177 case GL_RGBA:
6178 case GL_RGBA8:
6179 break;
6180 default:
6181 return true;
6184 GLint draw_framebuffer, read_framebuffer;
6186 // Cache framebuffer and texture bindings.
6187 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6188 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6190 if (!validation_texture_) {
6191 GLint bound_texture;
6192 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6194 // Create additional resources needed for the verification.
6195 glGenTextures(1, &validation_texture_);
6196 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6197 glGenFramebuffersEXT(1, &validation_fbo_);
6199 // Texture only needs to be 1x1.
6200 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6201 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6202 // multisample will fail if the color format of the source and destination
6203 // do not match. Here, we assume that the source is GL_RGBA, and make the
6204 // destination GL_RGBA. http://crbug.com/484203
6205 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6206 GL_UNSIGNED_BYTE, NULL);
6208 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6209 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6210 GL_TEXTURE_2D, validation_texture_, 0);
6212 glBindTexture(GL_TEXTURE_2D, bound_texture);
6215 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6216 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6217 GL_RENDERBUFFER, renderbuffer);
6219 // Cache current state and reset it to the values we require.
6220 GLboolean scissor_enabled = false;
6221 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6222 if (scissor_enabled)
6223 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6225 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6226 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6227 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6229 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6230 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6231 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6233 // Clear the buffer to the desired key color.
6234 glClear(GL_COLOR_BUFFER_BIT);
6236 // Blit from the multisample buffer to a standard texture.
6237 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6238 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6240 BlitFramebufferHelper(
6241 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6243 // Read a pixel from the buffer.
6244 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6246 unsigned char pixel[3] = {0, 0, 0};
6247 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6249 // Detach the renderbuffer.
6250 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6251 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6252 GL_RENDERBUFFER, 0);
6254 // Restore cached state.
6255 if (scissor_enabled)
6256 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6258 state_.SetDeviceColorMask(
6259 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6260 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6261 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6262 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6264 // Return true if the pixel matched the desired key color.
6265 return (pixel[0] == 0xFF &&
6266 pixel[1] == 0x00 &&
6267 pixel[2] == 0xFF);
6270 void GLES2DecoderImpl::DoRenderbufferStorage(
6271 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6272 Renderbuffer* renderbuffer =
6273 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6274 if (!renderbuffer) {
6275 LOCAL_SET_GL_ERROR(
6276 GL_INVALID_OPERATION,
6277 "glRenderbufferStorage", "no renderbuffer bound");
6278 return;
6281 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6282 height > renderbuffer_manager()->max_renderbuffer_size()) {
6283 LOCAL_SET_GL_ERROR(
6284 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6285 return;
6288 uint32 estimated_size = 0;
6289 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6290 width, height, 1, internalformat, &estimated_size)) {
6291 LOCAL_SET_GL_ERROR(
6292 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6293 return;
6296 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6297 LOCAL_SET_GL_ERROR(
6298 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6299 return;
6302 EnsureRenderbufferBound();
6303 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6304 glRenderbufferStorageEXT(
6305 target,
6306 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6307 internalformat),
6308 width,
6309 height);
6310 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6311 if (error == GL_NO_ERROR) {
6312 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6313 // we could just mark those framebuffers as not complete.
6314 framebuffer_manager()->IncFramebufferStateChangeCount();
6315 renderbuffer_manager()->SetInfo(
6316 renderbuffer, 1, internalformat, width, height);
6320 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6321 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6322 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6323 Program* program = GetProgramInfoNotShader(
6324 program_id, "glLinkProgram");
6325 if (!program) {
6326 return;
6329 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6330 if (program->Link(shader_manager(),
6331 workarounds().count_all_in_varyings_packing ?
6332 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6333 shader_cache_callback_)) {
6334 if (program == state_.current_program.get()) {
6335 if (workarounds().use_current_program_after_successful_link)
6336 glUseProgram(program->service_id());
6337 if (workarounds().clear_uniforms_before_first_program_use)
6338 program_manager()->ClearUniforms(program);
6342 // LinkProgram can be very slow. Exit command processing to allow for
6343 // context preemption and GPU watchdog checks.
6344 ExitCommandProcessingEarly();
6347 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6348 switch (src) {
6349 case GL_NONE:
6350 case GL_BACK:
6351 break;
6352 default:
6354 GLenum upper_limit = static_cast<GLenum>(
6355 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6356 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6357 LOCAL_SET_GL_ERROR(
6358 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6359 return;
6362 break;
6365 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6366 if (framebuffer) {
6367 if (src == GL_BACK) {
6368 LOCAL_SET_GL_ERROR(
6369 GL_INVALID_ENUM, "glReadBuffer",
6370 "invalid src for a named framebuffer");
6371 return;
6373 framebuffer->set_read_buffer(src);
6374 } else {
6375 if (src != GL_NONE && src != GL_BACK) {
6376 LOCAL_SET_GL_ERROR(
6377 GL_INVALID_ENUM, "glReadBuffer",
6378 "invalid src for the default framebuffer");
6379 return;
6381 back_buffer_read_buffer_ = src;
6382 if (GetBackbufferServiceId() && src == GL_BACK)
6383 src = GL_COLOR_ATTACHMENT0;
6385 glReadBuffer(src);
6388 void GLES2DecoderImpl::DoSamplerParameterfv(
6389 GLuint sampler, GLenum pname, const GLfloat* params) {
6390 DCHECK(params);
6391 glSamplerParameterf(sampler, pname, params[0]);
6394 void GLES2DecoderImpl::DoSamplerParameteriv(
6395 GLuint sampler, GLenum pname, const GLint* params) {
6396 DCHECK(params);
6397 glSamplerParameteri(sampler, pname, params[0]);
6400 void GLES2DecoderImpl::DoTexParameterf(
6401 GLenum target, GLenum pname, GLfloat param) {
6402 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6403 &state_, target);
6404 if (!texture) {
6405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6406 return;
6409 texture_manager()->SetParameterf(
6410 "glTexParameterf", GetErrorState(), texture, pname, param);
6413 void GLES2DecoderImpl::DoTexParameteri(
6414 GLenum target, GLenum pname, GLint param) {
6415 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6416 &state_, target);
6417 if (!texture) {
6418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6419 return;
6422 texture_manager()->SetParameteri(
6423 "glTexParameteri", GetErrorState(), texture, pname, param);
6426 void GLES2DecoderImpl::DoTexParameterfv(
6427 GLenum target, GLenum pname, const GLfloat* params) {
6428 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6429 &state_, target);
6430 if (!texture) {
6431 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6432 return;
6435 texture_manager()->SetParameterf(
6436 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6439 void GLES2DecoderImpl::DoTexParameteriv(
6440 GLenum target, GLenum pname, const GLint* params) {
6441 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6442 &state_, target);
6443 if (!texture) {
6444 LOCAL_SET_GL_ERROR(
6445 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6446 return;
6449 texture_manager()->SetParameteri(
6450 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6453 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6454 if (!state_.bound_valuebuffer.get()) {
6455 // There is no valuebuffer bound
6456 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6457 "no valuebuffer in use");
6458 return false;
6460 return true;
6463 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6464 GLenum subscription,
6465 const char* function_name) {
6466 if (!CheckCurrentValuebuffer(function_name)) {
6467 return false;
6469 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6470 // The valuebuffer is not subscribed to the target
6471 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6472 "valuebuffer is not subscribed");
6473 return false;
6475 return true;
6478 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6479 GLenum subscription,
6480 const char* function_name) {
6481 if (!CheckCurrentProgramForUniform(location, function_name)) {
6482 return false;
6484 GLint real_location = -1;
6485 GLint array_index = -1;
6486 const Program::UniformInfo* info =
6487 state_.current_program->GetUniformInfoByFakeLocation(
6488 location, &real_location, &array_index);
6489 if (!info) {
6490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6491 return false;
6493 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6494 info->accepts_api_type) == 0) {
6495 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6496 "wrong type for subscription");
6497 return false;
6499 return true;
6502 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6503 if (!state_.current_program.get()) {
6504 // The program does not exist.
6505 LOCAL_SET_GL_ERROR(
6506 GL_INVALID_OPERATION, function_name, "no program in use");
6507 return false;
6509 if (!state_.current_program->InUse()) {
6510 LOCAL_SET_GL_ERROR(
6511 GL_INVALID_OPERATION, function_name, "program not linked");
6512 return false;
6514 return true;
6517 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6518 GLint location, const char* function_name) {
6519 if (!CheckCurrentProgram(function_name)) {
6520 return false;
6522 return location != -1;
6525 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6526 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6527 if (!framebuffer)
6528 return false;
6529 const Framebuffer::Attachment* attachment =
6530 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6531 if (!attachment)
6532 return false;
6534 DCHECK(state_.current_program.get());
6535 const Program::SamplerIndices& sampler_indices =
6536 state_.current_program->sampler_indices();
6537 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6538 const Program::UniformInfo* uniform_info =
6539 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6540 DCHECK(uniform_info);
6541 if (uniform_info->type != GL_SAMPLER_2D)
6542 continue;
6543 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6544 GLuint texture_unit_index = uniform_info->texture_units[jj];
6545 if (texture_unit_index >= state_.texture_units.size())
6546 continue;
6547 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6548 TextureRef* texture_ref =
6549 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6550 if (attachment->IsTexture(texture_ref))
6551 return true;
6554 return false;
6557 bool GLES2DecoderImpl::CheckUniformForApiType(
6558 const Program::UniformInfo* info,
6559 const char* function_name,
6560 Program::UniformApiType api_type) {
6561 DCHECK(info);
6562 if ((api_type & info->accepts_api_type) == 0) {
6563 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6564 "wrong uniform function for type");
6565 return false;
6567 return true;
6570 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6571 GLint fake_location,
6572 const char* function_name,
6573 Program::UniformApiType api_type,
6574 GLint* real_location,
6575 GLenum* type,
6576 GLsizei* count) {
6577 DCHECK(type);
6578 DCHECK(count);
6579 DCHECK(real_location);
6581 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6582 return false;
6584 GLint array_index = -1;
6585 const Program::UniformInfo* info =
6586 state_.current_program->GetUniformInfoByFakeLocation(
6587 fake_location, real_location, &array_index);
6588 if (!info) {
6589 LOCAL_SET_GL_ERROR(
6590 GL_INVALID_OPERATION, function_name, "unknown location");
6591 return false;
6593 if (!CheckUniformForApiType(info, function_name, api_type)) {
6594 return false;
6596 if (*count > 1 && !info->is_array) {
6597 LOCAL_SET_GL_ERROR(
6598 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6599 return false;
6601 *count = std::min(info->size - array_index, *count);
6602 if (*count <= 0) {
6603 return false;
6605 *type = info->type;
6606 return true;
6609 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6610 GLenum type = 0;
6611 GLsizei count = 1;
6612 GLint real_location = -1;
6613 if (!PrepForSetUniformByLocation(fake_location,
6614 "glUniform1i",
6615 Program::kUniform1i,
6616 &real_location,
6617 &type,
6618 &count)) {
6619 return;
6621 if (!state_.current_program->SetSamplers(
6622 state_.texture_units.size(), fake_location, 1, &v0)) {
6623 LOCAL_SET_GL_ERROR(
6624 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6625 return;
6627 glUniform1i(real_location, v0);
6630 void GLES2DecoderImpl::DoUniform1iv(
6631 GLint fake_location, GLsizei count, const GLint *value) {
6632 GLenum type = 0;
6633 GLint real_location = -1;
6634 if (!PrepForSetUniformByLocation(fake_location,
6635 "glUniform1iv",
6636 Program::kUniform1i,
6637 &real_location,
6638 &type,
6639 &count)) {
6640 return;
6642 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6643 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6644 if (!state_.current_program->SetSamplers(
6645 state_.texture_units.size(), fake_location, count, value)) {
6646 LOCAL_SET_GL_ERROR(
6647 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6648 return;
6651 glUniform1iv(real_location, count, value);
6654 void GLES2DecoderImpl::DoUniform1fv(
6655 GLint fake_location, GLsizei count, const GLfloat* value) {
6656 GLenum type = 0;
6657 GLint real_location = -1;
6658 if (!PrepForSetUniformByLocation(fake_location,
6659 "glUniform1fv",
6660 Program::kUniform1f,
6661 &real_location,
6662 &type,
6663 &count)) {
6664 return;
6666 if (type == GL_BOOL) {
6667 scoped_ptr<GLint[]> temp(new GLint[count]);
6668 for (GLsizei ii = 0; ii < count; ++ii) {
6669 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6671 DoUniform1iv(real_location, count, temp.get());
6672 } else {
6673 glUniform1fv(real_location, count, value);
6677 void GLES2DecoderImpl::DoUniform2fv(
6678 GLint fake_location, GLsizei count, const GLfloat* value) {
6679 GLenum type = 0;
6680 GLint real_location = -1;
6681 if (!PrepForSetUniformByLocation(fake_location,
6682 "glUniform2fv",
6683 Program::kUniform2f,
6684 &real_location,
6685 &type,
6686 &count)) {
6687 return;
6689 if (type == GL_BOOL_VEC2) {
6690 GLsizei num_values = count * 2;
6691 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6692 for (GLsizei ii = 0; ii < num_values; ++ii) {
6693 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6695 glUniform2iv(real_location, count, temp.get());
6696 } else {
6697 glUniform2fv(real_location, count, value);
6701 void GLES2DecoderImpl::DoUniform3fv(
6702 GLint fake_location, GLsizei count, const GLfloat* value) {
6703 GLenum type = 0;
6704 GLint real_location = -1;
6705 if (!PrepForSetUniformByLocation(fake_location,
6706 "glUniform3fv",
6707 Program::kUniform3f,
6708 &real_location,
6709 &type,
6710 &count)) {
6711 return;
6713 if (type == GL_BOOL_VEC3) {
6714 GLsizei num_values = count * 3;
6715 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6716 for (GLsizei ii = 0; ii < num_values; ++ii) {
6717 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6719 glUniform3iv(real_location, count, temp.get());
6720 } else {
6721 glUniform3fv(real_location, count, value);
6725 void GLES2DecoderImpl::DoUniform4fv(
6726 GLint fake_location, GLsizei count, const GLfloat* value) {
6727 GLenum type = 0;
6728 GLint real_location = -1;
6729 if (!PrepForSetUniformByLocation(fake_location,
6730 "glUniform4fv",
6731 Program::kUniform4f,
6732 &real_location,
6733 &type,
6734 &count)) {
6735 return;
6737 if (type == GL_BOOL_VEC4) {
6738 GLsizei num_values = count * 4;
6739 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6740 for (GLsizei ii = 0; ii < num_values; ++ii) {
6741 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6743 glUniform4iv(real_location, count, temp.get());
6744 } else {
6745 glUniform4fv(real_location, count, value);
6749 void GLES2DecoderImpl::DoUniform2iv(
6750 GLint fake_location, GLsizei count, const GLint* value) {
6751 GLenum type = 0;
6752 GLint real_location = -1;
6753 if (!PrepForSetUniformByLocation(fake_location,
6754 "glUniform2iv",
6755 Program::kUniform2i,
6756 &real_location,
6757 &type,
6758 &count)) {
6759 return;
6761 glUniform2iv(real_location, count, value);
6764 void GLES2DecoderImpl::DoUniform3iv(
6765 GLint fake_location, GLsizei count, const GLint* value) {
6766 GLenum type = 0;
6767 GLint real_location = -1;
6768 if (!PrepForSetUniformByLocation(fake_location,
6769 "glUniform3iv",
6770 Program::kUniform3i,
6771 &real_location,
6772 &type,
6773 &count)) {
6774 return;
6776 glUniform3iv(real_location, count, value);
6779 void GLES2DecoderImpl::DoUniform4iv(
6780 GLint fake_location, GLsizei count, const GLint* value) {
6781 GLenum type = 0;
6782 GLint real_location = -1;
6783 if (!PrepForSetUniformByLocation(fake_location,
6784 "glUniform4iv",
6785 Program::kUniform4i,
6786 &real_location,
6787 &type,
6788 &count)) {
6789 return;
6791 glUniform4iv(real_location, count, value);
6794 void GLES2DecoderImpl::DoUniformMatrix2fv(
6795 GLint fake_location, GLsizei count, GLboolean transpose,
6796 const GLfloat* value) {
6797 GLenum type = 0;
6798 GLint real_location = -1;
6799 if (!PrepForSetUniformByLocation(fake_location,
6800 "glUniformMatrix2fv",
6801 Program::kUniformMatrix2f,
6802 &real_location,
6803 &type,
6804 &count)) {
6805 return;
6807 glUniformMatrix2fv(real_location, count, transpose, value);
6810 void GLES2DecoderImpl::DoUniformMatrix3fv(
6811 GLint fake_location, GLsizei count, GLboolean transpose,
6812 const GLfloat* value) {
6813 GLenum type = 0;
6814 GLint real_location = -1;
6815 if (!PrepForSetUniformByLocation(fake_location,
6816 "glUniformMatrix3fv",
6817 Program::kUniformMatrix3f,
6818 &real_location,
6819 &type,
6820 &count)) {
6821 return;
6823 glUniformMatrix3fv(real_location, count, transpose, value);
6826 void GLES2DecoderImpl::DoUniformMatrix4fv(
6827 GLint fake_location, GLsizei count, GLboolean transpose,
6828 const GLfloat* value) {
6829 GLenum type = 0;
6830 GLint real_location = -1;
6831 if (!PrepForSetUniformByLocation(fake_location,
6832 "glUniformMatrix4fv",
6833 Program::kUniformMatrix4f,
6834 &real_location,
6835 &type,
6836 &count)) {
6837 return;
6839 glUniformMatrix4fv(real_location, count, transpose, value);
6842 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6843 GLuint service_id = 0;
6844 Program* program = NULL;
6845 if (program_id) {
6846 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6847 if (!program) {
6848 return;
6850 if (!program->IsValid()) {
6851 // Program was not linked successfully. (ie, glLinkProgram)
6852 LOCAL_SET_GL_ERROR(
6853 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6854 return;
6856 service_id = program->service_id();
6858 if (state_.current_program.get()) {
6859 program_manager()->UnuseProgram(shader_manager(),
6860 state_.current_program.get());
6862 state_.current_program = program;
6863 LogClientServiceMapping("glUseProgram", program_id, service_id);
6864 glUseProgram(service_id);
6865 if (state_.current_program.get()) {
6866 program_manager()->UseProgram(state_.current_program.get());
6867 if (workarounds().clear_uniforms_before_first_program_use)
6868 program_manager()->ClearUniforms(program);
6872 void GLES2DecoderImpl::RenderWarning(
6873 const char* filename, int line, const std::string& msg) {
6874 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6877 void GLES2DecoderImpl::PerformanceWarning(
6878 const char* filename, int line, const std::string& msg) {
6879 logger_.LogMessage(filename, line,
6880 std::string("PERFORMANCE WARNING: ") + msg);
6883 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6884 Texture* texture, GLenum textarget) {
6885 // Image is already in use if texture is attached to a framebuffer.
6886 if (texture && !texture->IsAttachedToFramebuffer()) {
6887 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6888 if (image) {
6889 ScopedGLErrorSuppressor suppressor(
6890 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6891 GetErrorState());
6892 glBindTexture(textarget, texture->service_id());
6893 image->WillUseTexImage();
6894 RestoreCurrentTextureBindings(&state_, textarget);
6899 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6900 Texture* texture, GLenum textarget) {
6901 // Image is still in use if texture is attached to a framebuffer.
6902 if (texture && !texture->IsAttachedToFramebuffer()) {
6903 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6904 if (image) {
6905 ScopedGLErrorSuppressor suppressor(
6906 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6907 GetErrorState());
6908 glBindTexture(textarget, texture->service_id());
6909 image->DidUseTexImage();
6910 RestoreCurrentTextureBindings(&state_, textarget);
6915 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6916 DCHECK(state_.current_program.get());
6917 if (!texture_manager()->HaveUnrenderableTextures() &&
6918 !texture_manager()->HaveImages()) {
6919 return true;
6922 bool textures_set = false;
6923 const Program::SamplerIndices& sampler_indices =
6924 state_.current_program->sampler_indices();
6925 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6926 const Program::UniformInfo* uniform_info =
6927 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6928 DCHECK(uniform_info);
6929 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6930 GLuint texture_unit_index = uniform_info->texture_units[jj];
6931 if (texture_unit_index < state_.texture_units.size()) {
6932 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6933 TextureRef* texture_ref =
6934 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6935 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6936 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6937 textures_set = true;
6938 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6939 glBindTexture(
6940 textarget,
6941 texture_manager()->black_texture_id(uniform_info->type));
6942 if (!texture_ref) {
6943 LOCAL_RENDER_WARNING(
6944 std::string("there is no texture bound to the unit ") +
6945 base::IntToString(texture_unit_index));
6946 } else {
6947 LOCAL_RENDER_WARNING(
6948 std::string("texture bound to texture unit ") +
6949 base::IntToString(texture_unit_index) +
6950 " is not renderable. It maybe non-power-of-2 and have"
6951 " incompatible texture filtering.");
6953 continue;
6956 if (textarget != GL_TEXTURE_CUBE_MAP) {
6957 Texture* texture = texture_ref->texture();
6958 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6959 if (image && !texture->IsAttachedToFramebuffer()) {
6960 ScopedGLErrorSuppressor suppressor(
6961 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6962 textures_set = true;
6963 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6964 image->WillUseTexImage();
6965 continue;
6969 // else: should this be an error?
6972 return !textures_set;
6975 void GLES2DecoderImpl::RestoreStateForTextures() {
6976 DCHECK(state_.current_program.get());
6977 const Program::SamplerIndices& sampler_indices =
6978 state_.current_program->sampler_indices();
6979 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6980 const Program::UniformInfo* uniform_info =
6981 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6982 DCHECK(uniform_info);
6983 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6984 GLuint texture_unit_index = uniform_info->texture_units[jj];
6985 if (texture_unit_index < state_.texture_units.size()) {
6986 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6987 TextureRef* texture_ref =
6988 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6989 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6990 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6991 // Get the texture_ref info that was previously bound here.
6992 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6993 ? texture_unit.bound_texture_2d.get()
6994 : texture_unit.bound_texture_cube_map.get();
6995 glBindTexture(texture_unit.bind_target,
6996 texture_ref ? texture_ref->service_id() : 0);
6997 continue;
7000 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7001 Texture* texture = texture_ref->texture();
7002 gfx::GLImage* image =
7003 texture->GetLevelImage(texture_unit.bind_target, 0);
7004 if (image && !texture->IsAttachedToFramebuffer()) {
7005 ScopedGLErrorSuppressor suppressor(
7006 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7007 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7008 image->DidUseTexImage();
7009 continue;
7015 // Set the active texture back to whatever the user had it as.
7016 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7019 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7020 // Only check if there are some uncleared textures.
7021 if (!texture_manager()->HaveUnsafeTextures()) {
7022 return true;
7025 // 1: Check all textures we are about to render with.
7026 if (state_.current_program.get()) {
7027 const Program::SamplerIndices& sampler_indices =
7028 state_.current_program->sampler_indices();
7029 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7030 const Program::UniformInfo* uniform_info =
7031 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7032 DCHECK(uniform_info);
7033 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7034 GLuint texture_unit_index = uniform_info->texture_units[jj];
7035 if (texture_unit_index < state_.texture_units.size()) {
7036 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7037 TextureRef* texture_ref =
7038 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7039 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7040 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7041 return false;
7048 return true;
7051 bool GLES2DecoderImpl::IsDrawValid(
7052 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7053 GLsizei primcount) {
7054 DCHECK(instanced || primcount == 1);
7056 // NOTE: We specifically do not check current_program->IsValid() because
7057 // it could never be invalid since glUseProgram would have failed. While
7058 // glLinkProgram could later mark the program as invalid the previous
7059 // valid program will still function if it is still the current program.
7060 if (!state_.current_program.get()) {
7061 // The program does not exist.
7062 // But GL says no ERROR.
7063 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7064 return false;
7067 if (CheckDrawingFeedbackLoops()) {
7068 LOCAL_SET_GL_ERROR(
7069 GL_INVALID_OPERATION, function_name,
7070 "Source and destination textures of the draw are the same.");
7071 return false;
7074 return state_.vertex_attrib_manager
7075 ->ValidateBindings(function_name,
7076 this,
7077 feature_info_.get(),
7078 state_.current_program.get(),
7079 max_vertex_accessed,
7080 instanced,
7081 primcount);
7084 bool GLES2DecoderImpl::SimulateAttrib0(
7085 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7086 DCHECK(simulated);
7087 *simulated = false;
7089 if (feature_info_->gl_version_info().BehavesLikeGLES())
7090 return true;
7092 const VertexAttrib* attrib =
7093 state_.vertex_attrib_manager->GetVertexAttrib(0);
7094 // If it's enabled or it's not used then we don't need to do anything.
7095 bool attrib_0_used =
7096 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7097 if (attrib->enabled() && attrib_0_used) {
7098 return true;
7101 // Make a buffer with a single repeated vec4 value enough to
7102 // simulate the constant value that is supposed to be here.
7103 // This is required to emulate GLES2 on GL.
7104 GLuint num_vertices = max_vertex_accessed + 1;
7105 uint32 size_needed = 0;
7107 if (num_vertices == 0 ||
7108 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7109 size_needed > 0x7FFFFFFFU) {
7110 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7111 return false;
7114 LOCAL_PERFORMANCE_WARNING(
7115 "Attribute 0 is disabled. This has signficant performance penalty");
7117 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7118 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7120 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7121 if (new_buffer) {
7122 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7123 GLenum error = glGetError();
7124 if (error != GL_NO_ERROR) {
7125 LOCAL_SET_GL_ERROR(
7126 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7127 return false;
7131 const Vec4& value = state_.attrib_values[0];
7132 if (new_buffer ||
7133 (attrib_0_used &&
7134 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7135 // TODO(zmo): This is not 100% correct because we might lose data when
7136 // casting to float type, but it is a corner case and once we migrate to
7137 // core profiles on desktop GL, it is no longer relevant.
7138 Vec4f fvalue(value);
7139 std::vector<Vec4f> temp(num_vertices, fvalue);
7140 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7141 attrib_0_buffer_matches_value_ = true;
7142 attrib_0_value_ = value;
7143 attrib_0_size_ = size_needed;
7146 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7148 if (attrib->divisor())
7149 glVertexAttribDivisorANGLE(0, 0);
7151 *simulated = true;
7152 return true;
7155 void GLES2DecoderImpl::RestoreStateForAttrib(
7156 GLuint attrib_index, bool restore_array_binding) {
7157 const VertexAttrib* attrib =
7158 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7159 if (restore_array_binding) {
7160 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7161 Buffer* buffer = attrib->buffer();
7162 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7163 glVertexAttribPointer(
7164 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7165 attrib->gl_stride(), ptr);
7167 if (attrib->divisor())
7168 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7169 glBindBuffer(
7170 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7171 state_.bound_array_buffer->service_id() : 0);
7173 // Never touch vertex attribute 0's state (in particular, never
7174 // disable it) when running on desktop GL because it will never be
7175 // re-enabled.
7176 if (attrib_index != 0 ||
7177 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7178 if (attrib->enabled()) {
7179 glEnableVertexAttribArray(attrib_index);
7180 } else {
7181 glDisableVertexAttribArray(attrib_index);
7186 bool GLES2DecoderImpl::SimulateFixedAttribs(
7187 const char* function_name,
7188 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7189 DCHECK(simulated);
7190 *simulated = false;
7191 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7192 return true;
7194 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7195 return true;
7198 LOCAL_PERFORMANCE_WARNING(
7199 "GL_FIXED attributes have a signficant performance penalty");
7201 // NOTE: we could be smart and try to check if a buffer is used
7202 // twice in 2 different attribs, find the overlapping parts and therefore
7203 // duplicate the minimum amount of data but this whole code path is not meant
7204 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7205 // tests so we just add to the buffer attrib used.
7207 GLuint elements_needed = 0;
7208 const VertexAttribManager::VertexAttribList& enabled_attribs =
7209 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7210 for (VertexAttribManager::VertexAttribList::const_iterator it =
7211 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7212 const VertexAttrib* attrib = *it;
7213 const Program::VertexAttrib* attrib_info =
7214 state_.current_program->GetAttribInfoByLocation(attrib->index());
7215 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7216 max_vertex_accessed);
7217 GLuint num_vertices = max_accessed + 1;
7218 if (num_vertices == 0) {
7219 LOCAL_SET_GL_ERROR(
7220 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7221 return false;
7223 if (attrib_info &&
7224 attrib->CanAccess(max_accessed) &&
7225 attrib->type() == GL_FIXED) {
7226 uint32 elements_used = 0;
7227 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7228 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7229 LOCAL_SET_GL_ERROR(
7230 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7231 return false;
7236 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7237 uint32 size_needed = 0;
7238 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7239 size_needed > 0x7FFFFFFFU) {
7240 LOCAL_SET_GL_ERROR(
7241 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7242 return false;
7245 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7247 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7248 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7249 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7250 GLenum error = glGetError();
7251 if (error != GL_NO_ERROR) {
7252 LOCAL_SET_GL_ERROR(
7253 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7254 return false;
7258 // Copy the elements and convert to float
7259 GLintptr offset = 0;
7260 for (VertexAttribManager::VertexAttribList::const_iterator it =
7261 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7262 const VertexAttrib* attrib = *it;
7263 const Program::VertexAttrib* attrib_info =
7264 state_.current_program->GetAttribInfoByLocation(attrib->index());
7265 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7266 max_vertex_accessed);
7267 GLuint num_vertices = max_accessed + 1;
7268 if (num_vertices == 0) {
7269 LOCAL_SET_GL_ERROR(
7270 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7271 return false;
7273 if (attrib_info &&
7274 attrib->CanAccess(max_accessed) &&
7275 attrib->type() == GL_FIXED) {
7276 int num_elements = attrib->size() * num_vertices;
7277 const int src_size = num_elements * sizeof(int32);
7278 const int dst_size = num_elements * sizeof(float);
7279 scoped_ptr<float[]> data(new float[num_elements]);
7280 const int32* src = reinterpret_cast<const int32 *>(
7281 attrib->buffer()->GetRange(attrib->offset(), src_size));
7282 const int32* end = src + num_elements;
7283 float* dst = data.get();
7284 while (src != end) {
7285 *dst++ = static_cast<float>(*src++) / 65536.0f;
7287 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7288 glVertexAttribPointer(
7289 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7290 reinterpret_cast<GLvoid*>(offset));
7291 offset += dst_size;
7294 *simulated = true;
7295 return true;
7298 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7299 // There's no need to call glVertexAttribPointer because we shadow all the
7300 // settings and passing GL_FIXED to it will not work.
7301 glBindBuffer(
7302 GL_ARRAY_BUFFER,
7303 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7304 : 0);
7307 error::Error GLES2DecoderImpl::DoDrawArrays(
7308 const char* function_name,
7309 bool instanced,
7310 GLenum mode,
7311 GLint first,
7312 GLsizei count,
7313 GLsizei primcount) {
7314 error::Error error = WillAccessBoundFramebufferForDraw();
7315 if (error != error::kNoError)
7316 return error;
7317 if (!validators_->draw_mode.IsValid(mode)) {
7318 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7319 return error::kNoError;
7321 if (count < 0) {
7322 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7323 return error::kNoError;
7325 if (primcount < 0) {
7326 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7327 return error::kNoError;
7329 if (!CheckBoundFramebuffersValid(function_name)) {
7330 return error::kNoError;
7332 // We have to check this here because the prototype for glDrawArrays
7333 // is GLint not GLsizei.
7334 if (first < 0) {
7335 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7336 return error::kNoError;
7339 if (count == 0 || primcount == 0) {
7340 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7341 return error::kNoError;
7344 GLuint max_vertex_accessed = first + count - 1;
7345 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7346 if (!ClearUnclearedTextures()) {
7347 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7348 return error::kNoError;
7350 bool simulated_attrib_0 = false;
7351 if (!SimulateAttrib0(
7352 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7353 return error::kNoError;
7355 bool simulated_fixed_attribs = false;
7356 if (SimulateFixedAttribs(
7357 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7358 primcount)) {
7359 bool textures_set = !PrepareTexturesForRender();
7360 ApplyDirtyState();
7361 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7362 if (!instanced) {
7363 glDrawArrays(mode, first, count);
7364 } else {
7365 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7367 if (textures_set) {
7368 RestoreStateForTextures();
7370 if (simulated_fixed_attribs) {
7371 RestoreStateForSimulatedFixedAttribs();
7374 if (simulated_attrib_0) {
7375 // We don't have to restore attrib 0 generic data at the end of this
7376 // function even if it is simulated. This is because we will simulate
7377 // it in each draw call, and attrib 0 generic data queries use cached
7378 // values instead of passing down to the underlying driver.
7379 RestoreStateForAttrib(0, false);
7382 return error::kNoError;
7385 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7386 const void* cmd_data) {
7387 // TODO(zmo): crbug.com/481184
7388 // On Desktop GL with versions lower than 4.3, we need to emulate
7389 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7390 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7391 return DoDrawArrays("glDrawArrays",
7392 false,
7393 static_cast<GLenum>(c.mode),
7394 static_cast<GLint>(c.first),
7395 static_cast<GLsizei>(c.count),
7399 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7400 uint32 immediate_data_size,
7401 const void* cmd_data) {
7402 const gles2::cmds::DrawArraysInstancedANGLE& c =
7403 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7404 if (!features().angle_instanced_arrays) {
7405 LOCAL_SET_GL_ERROR(
7406 GL_INVALID_OPERATION,
7407 "glDrawArraysInstancedANGLE", "function not available");
7408 return error::kNoError;
7410 return DoDrawArrays("glDrawArraysIntancedANGLE",
7411 true,
7412 static_cast<GLenum>(c.mode),
7413 static_cast<GLint>(c.first),
7414 static_cast<GLsizei>(c.count),
7415 static_cast<GLsizei>(c.primcount));
7418 error::Error GLES2DecoderImpl::DoDrawElements(
7419 const char* function_name,
7420 bool instanced,
7421 GLenum mode,
7422 GLsizei count,
7423 GLenum type,
7424 int32 offset,
7425 GLsizei primcount) {
7426 error::Error error = WillAccessBoundFramebufferForDraw();
7427 if (error != error::kNoError)
7428 return error;
7429 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7430 LOCAL_SET_GL_ERROR(
7431 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7432 return error::kNoError;
7435 if (count < 0) {
7436 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7437 return error::kNoError;
7439 if (offset < 0) {
7440 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7441 return error::kNoError;
7443 if (!validators_->draw_mode.IsValid(mode)) {
7444 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7445 return error::kNoError;
7447 if (!validators_->index_type.IsValid(type)) {
7448 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7449 return error::kNoError;
7451 if (primcount < 0) {
7452 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7453 return error::kNoError;
7456 if (!CheckBoundFramebuffersValid(function_name)) {
7457 return error::kNoError;
7460 if (count == 0 || primcount == 0) {
7461 return error::kNoError;
7464 GLuint max_vertex_accessed;
7465 Buffer* element_array_buffer =
7466 state_.vertex_attrib_manager->element_array_buffer();
7468 if (!element_array_buffer->GetMaxValueForRange(
7469 offset, count, type, &max_vertex_accessed)) {
7470 LOCAL_SET_GL_ERROR(
7471 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7472 return error::kNoError;
7475 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7476 if (!ClearUnclearedTextures()) {
7477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7478 return error::kNoError;
7480 bool simulated_attrib_0 = false;
7481 if (!SimulateAttrib0(
7482 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7483 return error::kNoError;
7485 bool simulated_fixed_attribs = false;
7486 if (SimulateFixedAttribs(
7487 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7488 primcount)) {
7489 bool textures_set = !PrepareTexturesForRender();
7490 ApplyDirtyState();
7491 // TODO(gman): Refactor to hide these details in BufferManager or
7492 // VertexAttribManager.
7493 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7494 bool used_client_side_array = false;
7495 if (element_array_buffer->IsClientSideArray()) {
7496 used_client_side_array = true;
7497 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7498 indices = element_array_buffer->GetRange(offset, 0);
7501 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7502 if (!instanced) {
7503 glDrawElements(mode, count, type, indices);
7504 } else {
7505 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7508 if (used_client_side_array) {
7509 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7510 element_array_buffer->service_id());
7513 if (textures_set) {
7514 RestoreStateForTextures();
7516 if (simulated_fixed_attribs) {
7517 RestoreStateForSimulatedFixedAttribs();
7520 if (simulated_attrib_0) {
7521 // We don't have to restore attrib 0 generic data at the end of this
7522 // function even if it is simulated. This is because we will simulate
7523 // it in each draw call, and attrib 0 generic data queries use cached
7524 // values instead of passing down to the underlying driver.
7525 RestoreStateForAttrib(0, false);
7528 return error::kNoError;
7531 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7532 const void* cmd_data) {
7533 // TODO(zmo): crbug.com/481184
7534 // On Desktop GL with versions lower than 4.3, we need to emulate
7535 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7536 const gles2::cmds::DrawElements& c =
7537 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7538 return DoDrawElements("glDrawElements",
7539 false,
7540 static_cast<GLenum>(c.mode),
7541 static_cast<GLsizei>(c.count),
7542 static_cast<GLenum>(c.type),
7543 static_cast<int32>(c.index_offset),
7547 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7548 uint32 immediate_data_size,
7549 const void* cmd_data) {
7550 const gles2::cmds::DrawElementsInstancedANGLE& c =
7551 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7552 if (!features().angle_instanced_arrays) {
7553 LOCAL_SET_GL_ERROR(
7554 GL_INVALID_OPERATION,
7555 "glDrawElementsInstancedANGLE", "function not available");
7556 return error::kNoError;
7558 return DoDrawElements("glDrawElementsInstancedANGLE",
7559 true,
7560 static_cast<GLenum>(c.mode),
7561 static_cast<GLsizei>(c.count),
7562 static_cast<GLenum>(c.type),
7563 static_cast<int32>(c.index_offset),
7564 static_cast<GLsizei>(c.primcount));
7567 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7568 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7569 GLuint max_vertex_accessed = 0;
7570 Buffer* buffer = GetBuffer(buffer_id);
7571 if (!buffer) {
7572 // TODO(gman): Should this be a GL error or a command buffer error?
7573 LOCAL_SET_GL_ERROR(
7574 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7575 } else {
7576 if (!buffer->GetMaxValueForRange(
7577 offset, count, type, &max_vertex_accessed)) {
7578 // TODO(gman): Should this be a GL error or a command buffer error?
7579 LOCAL_SET_GL_ERROR(
7580 GL_INVALID_OPERATION,
7581 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7584 return max_vertex_accessed;
7587 void GLES2DecoderImpl::DoShaderSource(
7588 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7589 std::string str;
7590 for (GLsizei ii = 0; ii < count; ++ii) {
7591 if (length && length[ii] > 0)
7592 str.append(data[ii], length[ii]);
7593 else
7594 str.append(data[ii]);
7596 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7597 if (!shader) {
7598 return;
7600 // Note: We don't actually call glShaderSource here. We wait until
7601 // we actually compile the shader.
7602 shader->set_source(str);
7605 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7606 GLuint client_program_id, GLsizei count, const char* const* varyings,
7607 GLenum buffer_mode) {
7608 Program* program = GetProgramInfoNotShader(
7609 client_program_id, "glTransformFeedbackVaryings");
7610 if (!program) {
7611 return;
7613 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7614 glTransformFeedbackVaryings(
7615 program->service_id(), count, varyings, buffer_mode);
7618 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7619 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7620 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7621 if (!shader) {
7622 return;
7625 scoped_refptr<ShaderTranslatorInterface> translator;
7626 if (use_shader_translator_) {
7627 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7628 vertex_translator_ : fragment_translator_;
7631 const Shader::TranslatedShaderSourceType source_type =
7632 feature_info_->feature_flags().angle_translated_shader_source ?
7633 Shader::kANGLE : Shader::kGL;
7634 shader->RequestCompile(translator, source_type);
7637 void GLES2DecoderImpl::DoGetShaderiv(
7638 GLuint shader_id, GLenum pname, GLint* params) {
7639 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7640 if (!shader) {
7641 return;
7644 // Compile now for statuses that require it.
7645 switch (pname) {
7646 case GL_COMPILE_STATUS:
7647 case GL_INFO_LOG_LENGTH:
7648 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7649 shader->DoCompile();
7650 break;
7652 default:
7653 break;
7656 switch (pname) {
7657 case GL_SHADER_SOURCE_LENGTH:
7658 *params = shader->source().size();
7659 if (*params)
7660 ++(*params);
7661 return;
7662 case GL_COMPILE_STATUS:
7663 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7664 return;
7665 case GL_INFO_LOG_LENGTH:
7666 *params = shader->log_info().size();
7667 if (*params)
7668 ++(*params);
7669 return;
7670 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7671 *params = shader->translated_source().size();
7672 if (*params)
7673 ++(*params);
7674 return;
7675 default:
7676 break;
7678 glGetShaderiv(shader->service_id(), pname, params);
7681 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7682 const void* cmd_data) {
7683 const gles2::cmds::GetShaderSource& c =
7684 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7685 GLuint shader_id = c.shader;
7686 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7687 Bucket* bucket = CreateBucket(bucket_id);
7688 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7689 if (!shader || shader->source().empty()) {
7690 bucket->SetSize(0);
7691 return error::kNoError;
7693 bucket->SetFromString(shader->source().c_str());
7694 return error::kNoError;
7697 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7698 uint32 immediate_data_size,
7699 const void* cmd_data) {
7700 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7701 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7702 cmd_data);
7703 GLuint shader_id = c.shader;
7704 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7705 Bucket* bucket = CreateBucket(bucket_id);
7706 Shader* shader = GetShaderInfoNotProgram(
7707 shader_id, "glGetTranslatedShaderSourceANGLE");
7708 if (!shader) {
7709 bucket->SetSize(0);
7710 return error::kNoError;
7713 // Make sure translator has been utilized in compile.
7714 shader->DoCompile();
7716 bucket->SetFromString(shader->translated_source().c_str());
7717 return error::kNoError;
7720 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7721 uint32 immediate_data_size,
7722 const void* cmd_data) {
7723 const gles2::cmds::GetProgramInfoLog& c =
7724 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7725 GLuint program_id = c.program;
7726 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7727 Bucket* bucket = CreateBucket(bucket_id);
7728 Program* program = GetProgramInfoNotShader(
7729 program_id, "glGetProgramInfoLog");
7730 if (!program || !program->log_info()) {
7731 bucket->SetFromString("");
7732 return error::kNoError;
7734 bucket->SetFromString(program->log_info()->c_str());
7735 return error::kNoError;
7738 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7739 uint32 immediate_data_size,
7740 const void* cmd_data) {
7741 const gles2::cmds::GetShaderInfoLog& c =
7742 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7743 GLuint shader_id = c.shader;
7744 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7745 Bucket* bucket = CreateBucket(bucket_id);
7746 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7747 if (!shader) {
7748 bucket->SetFromString("");
7749 return error::kNoError;
7752 // Shader must be compiled in order to get the info log.
7753 shader->DoCompile();
7755 bucket->SetFromString(shader->log_info().c_str());
7756 return error::kNoError;
7759 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7760 return state_.GetEnabled(cap);
7763 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7764 const Buffer* buffer = GetBuffer(client_id);
7765 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7768 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7769 const Framebuffer* framebuffer =
7770 GetFramebuffer(client_id);
7771 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7774 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7775 // IsProgram is true for programs as soon as they are created, until they are
7776 // deleted and no longer in use.
7777 const Program* program = GetProgram(client_id);
7778 return program != NULL && !program->IsDeleted();
7781 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7782 const Renderbuffer* renderbuffer =
7783 GetRenderbuffer(client_id);
7784 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7787 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7788 // IsShader is true for shaders as soon as they are created, until they
7789 // are deleted and not attached to any programs.
7790 const Shader* shader = GetShader(client_id);
7791 return shader != NULL && !shader->IsDeleted();
7794 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7795 const TextureRef* texture_ref = GetTexture(client_id);
7796 return texture_ref && texture_ref->texture()->IsValid();
7799 void GLES2DecoderImpl::DoAttachShader(
7800 GLuint program_client_id, GLint shader_client_id) {
7801 Program* program = GetProgramInfoNotShader(
7802 program_client_id, "glAttachShader");
7803 if (!program) {
7804 return;
7806 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7807 if (!shader) {
7808 return;
7810 if (!program->AttachShader(shader_manager(), shader)) {
7811 LOCAL_SET_GL_ERROR(
7812 GL_INVALID_OPERATION,
7813 "glAttachShader",
7814 "can not attach more than one shader of the same type.");
7815 return;
7817 glAttachShader(program->service_id(), shader->service_id());
7820 void GLES2DecoderImpl::DoDetachShader(
7821 GLuint program_client_id, GLint shader_client_id) {
7822 Program* program = GetProgramInfoNotShader(
7823 program_client_id, "glDetachShader");
7824 if (!program) {
7825 return;
7827 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7828 if (!shader) {
7829 return;
7831 if (!program->DetachShader(shader_manager(), shader)) {
7832 LOCAL_SET_GL_ERROR(
7833 GL_INVALID_OPERATION,
7834 "glDetachShader", "shader not attached to program");
7835 return;
7837 glDetachShader(program->service_id(), shader->service_id());
7840 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7841 Program* program = GetProgramInfoNotShader(
7842 program_client_id, "glValidateProgram");
7843 if (!program) {
7844 return;
7846 program->Validate();
7849 void GLES2DecoderImpl::GetVertexAttribHelper(
7850 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7851 switch (pname) {
7852 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7854 Buffer* buffer = attrib->buffer();
7855 if (buffer && !buffer->IsDeleted()) {
7856 GLuint client_id;
7857 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7858 *params = client_id;
7860 break;
7862 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7863 *params = attrib->enabled();
7864 break;
7865 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7866 *params = attrib->size();
7867 break;
7868 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7869 *params = attrib->gl_stride();
7870 break;
7871 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7872 *params = attrib->type();
7873 break;
7874 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7875 *params = attrib->normalized();
7876 break;
7877 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7878 *params = attrib->divisor();
7879 break;
7880 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7881 *params = attrib->integer();
7882 break;
7883 default:
7884 NOTREACHED();
7885 break;
7889 void GLES2DecoderImpl::DoGetTexParameterfv(
7890 GLenum target, GLenum pname, GLfloat* params) {
7891 InitTextureMaxAnisotropyIfNeeded(target, pname);
7892 glGetTexParameterfv(target, pname, params);
7895 void GLES2DecoderImpl::DoGetTexParameteriv(
7896 GLenum target, GLenum pname, GLint* params) {
7897 InitTextureMaxAnisotropyIfNeeded(target, pname);
7898 glGetTexParameteriv(target, pname, params);
7901 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7902 GLenum target, GLenum pname) {
7903 if (!workarounds().init_texture_max_anisotropy)
7904 return;
7905 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7906 !validators_->texture_parameter.IsValid(pname)) {
7907 return;
7910 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7911 &state_, target);
7912 if (!texture_ref) {
7913 LOCAL_SET_GL_ERROR(
7914 GL_INVALID_OPERATION,
7915 "glGetTexParamter{fi}v", "unknown texture for target");
7916 return;
7918 Texture* texture = texture_ref->texture();
7919 texture->InitTextureMaxAnisotropyIfNeeded(target);
7922 template <typename T>
7923 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7924 GLuint index, GLenum pname, T* params) {
7925 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7926 if (!attrib) {
7927 LOCAL_SET_GL_ERROR(
7928 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7929 return;
7931 switch (pname) {
7932 case GL_CURRENT_VERTEX_ATTRIB:
7933 state_.attrib_values[index].GetValues(params);
7934 break;
7935 default: {
7936 GLint value = 0;
7937 GetVertexAttribHelper(attrib, pname, &value);
7938 *params = static_cast<T>(value);
7939 break;
7944 void GLES2DecoderImpl::DoGetVertexAttribfv(
7945 GLuint index, GLenum pname, GLfloat* params) {
7946 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7949 void GLES2DecoderImpl::DoGetVertexAttribiv(
7950 GLuint index, GLenum pname, GLint* params) {
7951 DoGetVertexAttribImpl<GLint>(index, pname, params);
7954 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7955 GLuint index, GLenum pname, GLint* params) {
7956 DoGetVertexAttribImpl<GLint>(index, pname, params);
7959 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7960 GLuint index, GLenum pname, GLuint* params) {
7961 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7964 template <typename T>
7965 bool GLES2DecoderImpl::SetVertexAttribValue(
7966 const char* function_name, GLuint index, const T* value) {
7967 if (index >= state_.attrib_values.size()) {
7968 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7969 return false;
7971 state_.attrib_values[index].SetValues(value);
7972 return true;
7975 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7976 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7977 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7978 glVertexAttrib1f(index, v0);
7982 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7983 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7984 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7985 glVertexAttrib2f(index, v0, v1);
7989 void GLES2DecoderImpl::DoVertexAttrib3f(
7990 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7991 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7992 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7993 glVertexAttrib3f(index, v0, v1, v2);
7997 void GLES2DecoderImpl::DoVertexAttrib4f(
7998 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7999 GLfloat v[4] = { v0, v1, v2, v3, };
8000 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8001 glVertexAttrib4f(index, v0, v1, v2, v3);
8005 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8006 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8007 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8008 glVertexAttrib1fv(index, v);
8012 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8013 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8014 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8015 glVertexAttrib2fv(index, v);
8019 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8020 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8021 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8022 glVertexAttrib3fv(index, v);
8026 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8027 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8028 glVertexAttrib4fv(index, v);
8032 void GLES2DecoderImpl::DoVertexAttribI4i(
8033 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8034 GLint v[4] = { v0, v1, v2, v3 };
8035 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8036 glVertexAttribI4i(index, v0, v1, v2, v3);
8040 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8041 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8042 glVertexAttribI4iv(index, v);
8046 void GLES2DecoderImpl::DoVertexAttribI4ui(
8047 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8048 GLuint v[4] = { v0, v1, v2, v3 };
8049 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8050 glVertexAttribI4ui(index, v0, v1, v2, v3);
8054 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8055 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8056 glVertexAttribI4uiv(index, v);
8060 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8061 uint32 immediate_data_size,
8062 const void* cmd_data) {
8063 if (!unsafe_es3_apis_enabled())
8064 return error::kUnknownCommand;
8065 const gles2::cmds::VertexAttribIPointer& c =
8066 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8068 if (!state_.bound_array_buffer.get() ||
8069 state_.bound_array_buffer->IsDeleted()) {
8070 if (state_.vertex_attrib_manager.get() ==
8071 state_.default_vertex_attrib_manager.get()) {
8072 LOCAL_SET_GL_ERROR(
8073 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8074 return error::kNoError;
8075 } else if (c.offset != 0) {
8076 LOCAL_SET_GL_ERROR(
8077 GL_INVALID_VALUE,
8078 "glVertexAttribIPointer", "client side arrays are not allowed");
8079 return error::kNoError;
8083 GLuint indx = c.indx;
8084 GLint size = c.size;
8085 GLenum type = c.type;
8086 GLsizei stride = c.stride;
8087 GLsizei offset = c.offset;
8088 const void* ptr = reinterpret_cast<const void*>(offset);
8089 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8090 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8091 return error::kNoError;
8093 if (!validators_->vertex_attrib_size.IsValid(size)) {
8094 LOCAL_SET_GL_ERROR(
8095 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8096 return error::kNoError;
8098 if (indx >= group_->max_vertex_attribs()) {
8099 LOCAL_SET_GL_ERROR(
8100 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8101 return error::kNoError;
8103 if (stride < 0) {
8104 LOCAL_SET_GL_ERROR(
8105 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8106 return error::kNoError;
8108 if (stride > 255) {
8109 LOCAL_SET_GL_ERROR(
8110 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8111 return error::kNoError;
8113 if (offset < 0) {
8114 LOCAL_SET_GL_ERROR(
8115 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8116 return error::kNoError;
8118 GLsizei component_size =
8119 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8120 // component_size must be a power of two to use & as optimized modulo.
8121 DCHECK(GLES2Util::IsPOT(component_size));
8122 if (offset & (component_size - 1)) {
8123 LOCAL_SET_GL_ERROR(
8124 GL_INVALID_OPERATION,
8125 "glVertexAttribIPointer", "offset not valid for type");
8126 return error::kNoError;
8128 if (stride & (component_size - 1)) {
8129 LOCAL_SET_GL_ERROR(
8130 GL_INVALID_OPERATION,
8131 "glVertexAttribIPointer", "stride not valid for type");
8132 return error::kNoError;
8134 state_.vertex_attrib_manager
8135 ->SetAttribInfo(indx,
8136 state_.bound_array_buffer.get(),
8137 size,
8138 type,
8139 GL_FALSE,
8140 stride,
8141 stride != 0 ? stride : component_size * size,
8142 offset,
8143 GL_TRUE);
8144 glVertexAttribIPointer(indx, size, type, stride, ptr);
8145 return error::kNoError;
8148 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8149 uint32 immediate_data_size,
8150 const void* cmd_data) {
8151 const gles2::cmds::VertexAttribPointer& c =
8152 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8154 if (!state_.bound_array_buffer.get() ||
8155 state_.bound_array_buffer->IsDeleted()) {
8156 if (state_.vertex_attrib_manager.get() ==
8157 state_.default_vertex_attrib_manager.get()) {
8158 LOCAL_SET_GL_ERROR(
8159 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8160 return error::kNoError;
8161 } else if (c.offset != 0) {
8162 LOCAL_SET_GL_ERROR(
8163 GL_INVALID_VALUE,
8164 "glVertexAttribPointer", "client side arrays are not allowed");
8165 return error::kNoError;
8169 GLuint indx = c.indx;
8170 GLint size = c.size;
8171 GLenum type = c.type;
8172 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8173 GLsizei stride = c.stride;
8174 GLsizei offset = c.offset;
8175 const void* ptr = reinterpret_cast<const void*>(offset);
8176 if (!validators_->vertex_attrib_type.IsValid(type)) {
8177 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8178 return error::kNoError;
8180 if (!validators_->vertex_attrib_size.IsValid(size)) {
8181 LOCAL_SET_GL_ERROR(
8182 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8183 return error::kNoError;
8185 if (indx >= group_->max_vertex_attribs()) {
8186 LOCAL_SET_GL_ERROR(
8187 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8188 return error::kNoError;
8190 if (stride < 0) {
8191 LOCAL_SET_GL_ERROR(
8192 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8193 return error::kNoError;
8195 if (stride > 255) {
8196 LOCAL_SET_GL_ERROR(
8197 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8198 return error::kNoError;
8200 if (offset < 0) {
8201 LOCAL_SET_GL_ERROR(
8202 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8203 return error::kNoError;
8205 GLsizei component_size =
8206 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8207 // component_size must be a power of two to use & as optimized modulo.
8208 DCHECK(GLES2Util::IsPOT(component_size));
8209 if (offset & (component_size - 1)) {
8210 LOCAL_SET_GL_ERROR(
8211 GL_INVALID_OPERATION,
8212 "glVertexAttribPointer", "offset not valid for type");
8213 return error::kNoError;
8215 if (stride & (component_size - 1)) {
8216 LOCAL_SET_GL_ERROR(
8217 GL_INVALID_OPERATION,
8218 "glVertexAttribPointer", "stride not valid for type");
8219 return error::kNoError;
8221 state_.vertex_attrib_manager
8222 ->SetAttribInfo(indx,
8223 state_.bound_array_buffer.get(),
8224 size,
8225 type,
8226 normalized,
8227 stride,
8228 stride != 0 ? stride : component_size * size,
8229 offset,
8230 GL_FALSE);
8231 // We support GL_FIXED natively on EGL/GLES2 implementations
8232 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8233 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8235 return error::kNoError;
8238 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8239 GLsizei height) {
8240 state_.viewport_x = x;
8241 state_.viewport_y = y;
8242 state_.viewport_width = std::min(width, viewport_max_width_);
8243 state_.viewport_height = std::min(height, viewport_max_height_);
8244 glViewport(x, y, width, height);
8247 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8248 uint32 immediate_data_size,
8249 const void* cmd_data) {
8250 const gles2::cmds::VertexAttribDivisorANGLE& c =
8251 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8252 if (!features().angle_instanced_arrays) {
8253 LOCAL_SET_GL_ERROR(
8254 GL_INVALID_OPERATION,
8255 "glVertexAttribDivisorANGLE", "function not available");
8256 return error::kNoError;
8258 GLuint index = c.index;
8259 GLuint divisor = c.divisor;
8260 if (index >= group_->max_vertex_attribs()) {
8261 LOCAL_SET_GL_ERROR(
8262 GL_INVALID_VALUE,
8263 "glVertexAttribDivisorANGLE", "index out of range");
8264 return error::kNoError;
8267 state_.vertex_attrib_manager->SetDivisor(
8268 index,
8269 divisor);
8270 glVertexAttribDivisorANGLE(index, divisor);
8271 return error::kNoError;
8274 template <typename pixel_data_type>
8275 static void WriteAlphaData(
8276 void* pixels, uint32 row_count, uint32 channel_count,
8277 uint32 alpha_channel_index, uint32 unpadded_row_size,
8278 uint32 padded_row_size, pixel_data_type alpha_value) {
8279 DCHECK_GT(channel_count, 0U);
8280 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8281 uint32 unpadded_row_size_in_elements =
8282 unpadded_row_size / sizeof(pixel_data_type);
8283 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8284 uint32 padded_row_size_in_elements =
8285 padded_row_size / sizeof(pixel_data_type);
8286 pixel_data_type* dst =
8287 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8288 for (uint32 yy = 0; yy < row_count; ++yy) {
8289 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8290 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8291 *d = alpha_value;
8293 dst += padded_row_size_in_elements;
8297 void GLES2DecoderImpl::FinishReadPixels(
8298 const cmds::ReadPixels& c,
8299 GLuint buffer) {
8300 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8301 GLsizei width = c.width;
8302 GLsizei height = c.height;
8303 GLenum format = c.format;
8304 GLenum type = c.type;
8305 typedef cmds::ReadPixels::Result Result;
8306 uint32 pixels_size;
8307 Result* result = NULL;
8308 if (c.result_shm_id != 0) {
8309 result = GetSharedMemoryAs<Result*>(
8310 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8311 if (!result) {
8312 if (buffer != 0) {
8313 glDeleteBuffersARB(1, &buffer);
8315 return;
8318 GLES2Util::ComputeImageDataSizes(
8319 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8320 NULL, NULL);
8321 void* pixels = GetSharedMemoryAs<void*>(
8322 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8323 if (!pixels) {
8324 if (buffer != 0) {
8325 glDeleteBuffersARB(1, &buffer);
8327 return;
8330 if (buffer != 0) {
8331 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8332 void* data;
8333 if (features().map_buffer_range) {
8334 data = glMapBufferRange(
8335 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8336 } else {
8337 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8339 if (!data) {
8340 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8341 "Unable to map memory for readback.");
8342 return;
8344 memcpy(pixels, data, pixels_size);
8345 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8346 // have to restore the state.
8347 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8348 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8349 glDeleteBuffersARB(1, &buffer);
8352 if (result != NULL) {
8353 *result = true;
8356 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8357 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8358 if ((channels_exist & 0x0008) == 0 &&
8359 workarounds().clear_alpha_in_readpixels) {
8360 // Set the alpha to 255 because some drivers are buggy in this regard.
8361 uint32 temp_size;
8363 uint32 unpadded_row_size;
8364 uint32 padded_row_size;
8365 if (!GLES2Util::ComputeImageDataSizes(
8366 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8367 &unpadded_row_size, &padded_row_size)) {
8368 return;
8371 uint32 channel_count = 0;
8372 uint32 alpha_channel = 0;
8373 switch (format) {
8374 case GL_RGBA:
8375 case GL_BGRA_EXT:
8376 channel_count = 4;
8377 alpha_channel = 3;
8378 break;
8379 case GL_ALPHA:
8380 channel_count = 1;
8381 alpha_channel = 0;
8382 break;
8385 if (channel_count > 0) {
8386 switch (type) {
8387 case GL_UNSIGNED_BYTE:
8388 WriteAlphaData<uint8>(
8389 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8390 padded_row_size, 0xFF);
8391 break;
8392 case GL_FLOAT:
8393 WriteAlphaData<float>(
8394 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8395 padded_row_size, 1.0f);
8396 break;
8397 case GL_HALF_FLOAT:
8398 WriteAlphaData<uint16>(
8399 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8400 padded_row_size, 0x3C00);
8401 break;
8407 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8408 const void* cmd_data) {
8409 const gles2::cmds::ReadPixels& c =
8410 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8411 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8412 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8413 if (fbo_error != error::kNoError)
8414 return fbo_error;
8415 GLint x = c.x;
8416 GLint y = c.y;
8417 GLsizei width = c.width;
8418 GLsizei height = c.height;
8419 GLenum format = c.format;
8420 GLenum type = c.type;
8421 GLboolean async = static_cast<GLboolean>(c.async);
8422 if (width < 0 || height < 0) {
8423 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8424 return error::kNoError;
8426 typedef cmds::ReadPixels::Result Result;
8427 uint32 pixels_size;
8428 if (!GLES2Util::ComputeImageDataSizes(
8429 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8430 NULL, NULL)) {
8431 return error::kOutOfBounds;
8433 void* pixels = GetSharedMemoryAs<void*>(
8434 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8435 if (!pixels) {
8436 return error::kOutOfBounds;
8438 Result* result = NULL;
8439 if (c.result_shm_id != 0) {
8440 result = GetSharedMemoryAs<Result*>(
8441 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8442 if (!result) {
8443 return error::kOutOfBounds;
8447 if (!validators_->read_pixel_format.IsValid(format)) {
8448 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8449 return error::kNoError;
8451 if (!validators_->read_pixel_type.IsValid(type)) {
8452 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8453 return error::kNoError;
8455 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
8456 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
8457 // format and type are acceptable enums but not guaranteed to be supported
8458 // for this framebuffer. Have to ask gl if they are valid.
8459 GLint preferred_format = 0;
8460 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8461 GLint preferred_type = 0;
8462 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8463 if (format != static_cast<GLenum>(preferred_format) ||
8464 type != static_cast<GLenum>(preferred_type)) {
8465 LOCAL_SET_GL_ERROR(
8466 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
8467 "with the current read framebuffer");
8468 return error::kNoError;
8471 if (width == 0 || height == 0) {
8472 return error::kNoError;
8475 // Get the size of the current fbo or backbuffer.
8476 gfx::Size max_size = GetBoundReadFrameBufferSize();
8478 int32 max_x;
8479 int32 max_y;
8480 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8481 LOCAL_SET_GL_ERROR(
8482 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8483 return error::kNoError;
8486 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8487 return error::kNoError;
8490 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8491 return error::kNoError;
8494 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8496 ScopedResolvedFrameBufferBinder binder(this, false, true);
8498 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8499 // The user requested an out of range area. Get the results 1 line
8500 // at a time.
8501 uint32 temp_size;
8502 uint32 unpadded_row_size;
8503 uint32 padded_row_size;
8504 if (!GLES2Util::ComputeImageDataSizes(
8505 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8506 &unpadded_row_size, &padded_row_size)) {
8507 LOCAL_SET_GL_ERROR(
8508 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8509 return error::kNoError;
8512 GLint dest_x_offset = std::max(-x, 0);
8513 uint32 dest_row_offset;
8514 if (!GLES2Util::ComputeImageDataSizes(
8515 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8516 &dest_row_offset, NULL, NULL)) {
8517 LOCAL_SET_GL_ERROR(
8518 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8519 return error::kNoError;
8522 // Copy each row into the larger dest rect.
8523 int8* dst = static_cast<int8*>(pixels);
8524 GLint read_x = std::max(0, x);
8525 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8526 GLint read_width = read_end_x - read_x;
8527 for (GLint yy = 0; yy < height; ++yy) {
8528 GLint ry = y + yy;
8530 // Clear the row.
8531 memset(dst, 0, unpadded_row_size);
8533 // If the row is in range, copy it.
8534 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8535 glReadPixels(
8536 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8538 dst += padded_row_size;
8540 } else {
8541 if (async && features().use_async_readpixels) {
8542 GLuint buffer = 0;
8543 glGenBuffersARB(1, &buffer);
8544 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8545 // For ANGLE client version 2, GL_STREAM_READ is not available.
8546 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8547 GL_STATIC_DRAW : GL_STREAM_READ;
8548 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8549 GLenum error = glGetError();
8550 if (error == GL_NO_ERROR) {
8551 glReadPixels(x, y, width, height, format, type, 0);
8552 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8553 new FenceCallback()));
8554 WaitForReadPixels(base::Bind(
8555 &GLES2DecoderImpl::FinishReadPixels,
8556 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8557 <GLES2DecoderImpl>(this),
8558 c, buffer));
8559 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8560 return error::kNoError;
8561 } else {
8562 // On error, unbind pack buffer and fall through to sync readpixels
8563 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8564 glDeleteBuffersARB(1, &buffer);
8567 glReadPixels(x, y, width, height, format, type, pixels);
8569 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8570 if (error == GL_NO_ERROR) {
8571 if (result != NULL) {
8572 *result = true;
8574 FinishReadPixels(c, 0);
8577 return error::kNoError;
8580 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8581 const void* cmd_data) {
8582 const gles2::cmds::PixelStorei& c =
8583 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8584 GLenum pname = c.pname;
8585 GLenum param = c.param;
8586 if (!validators_->pixel_store.IsValid(pname)) {
8587 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8588 return error::kNoError;
8590 switch (pname) {
8591 case GL_PACK_ALIGNMENT:
8592 case GL_UNPACK_ALIGNMENT:
8593 if (!validators_->pixel_store_alignment.IsValid(param)) {
8594 LOCAL_SET_GL_ERROR(
8595 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8596 return error::kNoError;
8598 break;
8599 default:
8600 break;
8602 glPixelStorei(pname, param);
8603 switch (pname) {
8604 case GL_PACK_ALIGNMENT:
8605 state_.pack_alignment = param;
8606 break;
8607 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8608 state_.pack_reverse_row_order = (param != 0);
8609 break;
8610 case GL_UNPACK_ALIGNMENT:
8611 state_.unpack_alignment = param;
8612 break;
8613 default:
8614 // Validation should have prevented us from getting here.
8615 NOTREACHED();
8616 break;
8618 return error::kNoError;
8621 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8622 uint32 immediate_data_size,
8623 const void* cmd_data) {
8624 const gles2::cmds::PostSubBufferCHROMIUM& c =
8625 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8626 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8628 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8630 if (!supports_post_sub_buffer_) {
8631 LOCAL_SET_GL_ERROR(
8632 GL_INVALID_OPERATION,
8633 "glPostSubBufferCHROMIUM", "command not supported by surface");
8634 return error::kNoError;
8636 bool is_tracing;
8637 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8638 &is_tracing);
8639 if (is_tracing) {
8640 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8641 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8642 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8643 is_offscreen ? offscreen_size_ : surface_->GetSize());
8645 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8646 gfx::SwapResult::SWAP_FAILED) {
8647 return error::kNoError;
8648 } else {
8649 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8650 return error::kLostContext;
8654 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8655 uint32 immediate_data_size,
8656 const void* cmd_data) {
8657 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8658 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8659 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8660 if (!ref) {
8661 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8662 "glScheduleOverlayPlaneCHROMIUM",
8663 "unknown texture");
8664 return error::kNoError;
8666 gfx::GLImage* image =
8667 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8668 if (!image) {
8669 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8670 "glScheduleOverlayPlaneCHROMIUM",
8671 "unsupported texture format");
8672 return error::kNoError;
8674 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8675 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8676 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8677 "glScheduleOverlayPlaneCHROMIUM",
8678 "invalid transform enum");
8679 return error::kNoError;
8681 if (!surface_->ScheduleOverlayPlane(
8682 c.plane_z_order,
8683 transform,
8684 image,
8685 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8686 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8687 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8688 "glScheduleOverlayPlaneCHROMIUM",
8689 "failed to schedule overlay");
8691 return error::kNoError;
8694 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8695 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8696 const std::string& name_str) {
8697 if (!StringIsValidForGLES(name_str.c_str())) {
8698 LOCAL_SET_GL_ERROR(
8699 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8700 return error::kNoError;
8702 Program* program = GetProgramInfoNotShader(
8703 client_id, "glGetAttribLocation");
8704 if (!program) {
8705 return error::kNoError;
8707 if (!program->IsValid()) {
8708 LOCAL_SET_GL_ERROR(
8709 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8710 return error::kNoError;
8712 GLint* location = GetSharedMemoryAs<GLint*>(
8713 location_shm_id, location_shm_offset, sizeof(GLint));
8714 if (!location) {
8715 return error::kOutOfBounds;
8717 // Require the client to init this incase the context is lost and we are no
8718 // longer executing commands.
8719 if (*location != -1) {
8720 return error::kGenericError;
8722 *location = program->GetAttribLocation(name_str);
8723 return error::kNoError;
8726 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8727 uint32 immediate_data_size,
8728 const void* cmd_data) {
8729 const gles2::cmds::GetAttribLocation& c =
8730 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8731 Bucket* bucket = GetBucket(c.name_bucket_id);
8732 if (!bucket) {
8733 return error::kInvalidArguments;
8735 std::string name_str;
8736 if (!bucket->GetAsString(&name_str)) {
8737 return error::kInvalidArguments;
8739 return GetAttribLocationHelper(
8740 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8743 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8744 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8745 const std::string& name_str) {
8746 if (!StringIsValidForGLES(name_str.c_str())) {
8747 LOCAL_SET_GL_ERROR(
8748 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8749 return error::kNoError;
8751 Program* program = GetProgramInfoNotShader(
8752 client_id, "glGetUniformLocation");
8753 if (!program) {
8754 return error::kNoError;
8756 if (!program->IsValid()) {
8757 LOCAL_SET_GL_ERROR(
8758 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8759 return error::kNoError;
8761 GLint* location = GetSharedMemoryAs<GLint*>(
8762 location_shm_id, location_shm_offset, sizeof(GLint));
8763 if (!location) {
8764 return error::kOutOfBounds;
8766 // Require the client to init this incase the context is lost an we are no
8767 // longer executing commands.
8768 if (*location != -1) {
8769 return error::kGenericError;
8771 *location = program->GetUniformFakeLocation(name_str);
8772 return error::kNoError;
8775 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8776 uint32 immediate_data_size,
8777 const void* cmd_data) {
8778 const gles2::cmds::GetUniformLocation& c =
8779 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8780 Bucket* bucket = GetBucket(c.name_bucket_id);
8781 if (!bucket) {
8782 return error::kInvalidArguments;
8784 std::string name_str;
8785 if (!bucket->GetAsString(&name_str)) {
8786 return error::kInvalidArguments;
8788 return GetUniformLocationHelper(
8789 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8792 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8793 uint32 immediate_data_size,
8794 const void* cmd_data) {
8795 if (!unsafe_es3_apis_enabled())
8796 return error::kUnknownCommand;
8797 const gles2::cmds::GetUniformIndices& c =
8798 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8799 Bucket* bucket = GetBucket(c.names_bucket_id);
8800 if (!bucket) {
8801 return error::kInvalidArguments;
8803 GLsizei count = 0;
8804 std::vector<char*> names;
8805 std::vector<GLint> len;
8806 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8807 return error::kInvalidArguments;
8809 typedef cmds::GetUniformIndices::Result Result;
8810 Result* result = GetSharedMemoryAs<Result*>(
8811 c.indices_shm_id, c.indices_shm_offset,
8812 Result::ComputeSize(static_cast<size_t>(count)));
8813 GLuint* indices = result ? result->GetData() : NULL;
8814 if (indices == NULL) {
8815 return error::kOutOfBounds;
8817 // Check that the client initialized the result.
8818 if (result->size != 0) {
8819 return error::kInvalidArguments;
8821 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8822 if (!program) {
8823 return error::kNoError;
8825 GLuint service_id = program->service_id();
8826 GLint link_status = GL_FALSE;
8827 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8828 if (link_status != GL_TRUE) {
8829 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8830 "glGetUniformIndices", "program not linked");
8831 return error::kNoError;
8833 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8834 glGetUniformIndices(service_id, count, &names[0], indices);
8835 GLenum error = glGetError();
8836 if (error == GL_NO_ERROR) {
8837 result->SetNumResults(count);
8838 } else {
8839 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8841 return error::kNoError;
8844 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8845 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8846 const std::string& name_str) {
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 and we are no
8853 // longer executing commands.
8854 if (*location != -1) {
8855 return error::kGenericError;
8857 Program* program = GetProgramInfoNotShader(
8858 client_id, "glGetFragDataLocation");
8859 if (!program) {
8860 return error::kNoError;
8862 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8863 return error::kNoError;
8866 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8867 uint32 immediate_data_size,
8868 const void* cmd_data) {
8869 if (!unsafe_es3_apis_enabled())
8870 return error::kUnknownCommand;
8871 const gles2::cmds::GetFragDataLocation& c =
8872 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8873 Bucket* bucket = GetBucket(c.name_bucket_id);
8874 if (!bucket) {
8875 return error::kInvalidArguments;
8877 std::string name_str;
8878 if (!bucket->GetAsString(&name_str)) {
8879 return error::kInvalidArguments;
8881 return GetFragDataLocationHelper(
8882 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8885 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8886 uint32 immediate_data_size, const void* cmd_data) {
8887 if (!unsafe_es3_apis_enabled())
8888 return error::kUnknownCommand;
8889 const gles2::cmds::GetUniformBlockIndex& c =
8890 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8891 Bucket* bucket = GetBucket(c.name_bucket_id);
8892 if (!bucket) {
8893 return error::kInvalidArguments;
8895 std::string name_str;
8896 if (!bucket->GetAsString(&name_str)) {
8897 return error::kInvalidArguments;
8899 GLuint* index = GetSharedMemoryAs<GLuint*>(
8900 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8901 if (!index) {
8902 return error::kOutOfBounds;
8904 // Require the client to init this in case the context is lost and we are no
8905 // longer executing commands.
8906 if (*index != GL_INVALID_INDEX) {
8907 return error::kGenericError;
8909 Program* program = GetProgramInfoNotShader(
8910 c.program, "glGetUniformBlockIndex");
8911 if (!program) {
8912 return error::kNoError;
8914 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8915 return error::kNoError;
8918 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8919 const void* cmd_data) {
8920 const gles2::cmds::GetString& c =
8921 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8922 GLenum name = static_cast<GLenum>(c.name);
8923 if (!validators_->string_type.IsValid(name)) {
8924 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8925 return error::kNoError;
8928 const char* str = nullptr;
8929 std::string extensions;
8930 switch (name) {
8931 case GL_VERSION:
8932 if (unsafe_es3_apis_enabled())
8933 str = "OpenGL ES 3.0 Chromium";
8934 else
8935 str = "OpenGL ES 2.0 Chromium";
8936 break;
8937 case GL_SHADING_LANGUAGE_VERSION:
8938 if (unsafe_es3_apis_enabled())
8939 str = "OpenGL ES GLSL ES 3.0 Chromium";
8940 else
8941 str = "OpenGL ES GLSL ES 1.0 Chromium";
8942 break;
8943 case GL_RENDERER:
8944 case GL_VENDOR:
8945 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8946 // They are used by WEBGL_debug_renderer_info.
8947 if (!IsWebGLContext())
8948 str = "Chromium";
8949 else
8950 str = reinterpret_cast<const char*>(glGetString(name));
8951 break;
8952 case GL_EXTENSIONS:
8954 // For WebGL contexts, strip out the OES derivatives and
8955 // EXT frag depth extensions if they have not been enabled.
8956 if (IsWebGLContext()) {
8957 extensions = feature_info_->extensions();
8958 if (!derivatives_explicitly_enabled_) {
8959 size_t offset = extensions.find(kOESDerivativeExtension);
8960 if (std::string::npos != offset) {
8961 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8962 std::string());
8965 if (!frag_depth_explicitly_enabled_) {
8966 size_t offset = extensions.find(kEXTFragDepthExtension);
8967 if (std::string::npos != offset) {
8968 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8969 std::string());
8972 if (!draw_buffers_explicitly_enabled_) {
8973 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8974 if (std::string::npos != offset) {
8975 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8976 std::string());
8979 if (!shader_texture_lod_explicitly_enabled_) {
8980 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8981 if (std::string::npos != offset) {
8982 extensions.replace(offset,
8983 arraysize(kEXTShaderTextureLodExtension),
8984 std::string());
8987 } else {
8988 extensions = feature_info_->extensions().c_str();
8990 if (supports_post_sub_buffer_)
8991 extensions += " GL_CHROMIUM_post_sub_buffer";
8992 str = extensions.c_str();
8994 break;
8995 default:
8996 str = reinterpret_cast<const char*>(glGetString(name));
8997 break;
8999 Bucket* bucket = CreateBucket(c.bucket_id);
9000 bucket->SetFromString(str);
9001 return error::kNoError;
9004 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9005 const void* cmd_data) {
9006 const gles2::cmds::BufferData& c =
9007 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9008 GLenum target = static_cast<GLenum>(c.target);
9009 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9010 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9011 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9012 GLenum usage = static_cast<GLenum>(c.usage);
9013 const void* data = NULL;
9014 if (data_shm_id != 0 || data_shm_offset != 0) {
9015 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9016 if (!data) {
9017 return error::kOutOfBounds;
9020 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9021 return error::kNoError;
9024 void GLES2DecoderImpl::DoBufferSubData(
9025 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9026 // Just delegate it. Some validation is actually done before this.
9027 buffer_manager()->ValidateAndDoBufferSubData(
9028 &state_, target, offset, size, data);
9031 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9032 unsigned target,
9033 int level,
9034 unsigned format,
9035 unsigned type,
9036 int xoffset,
9037 int yoffset,
9038 int width,
9039 int height) {
9040 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9041 if ((feature_info_->feature_flags().angle_depth_texture ||
9042 feature_info_->IsES3Enabled())
9043 && (channels & GLES2Util::kDepth) != 0) {
9044 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9045 // on depth formats.
9046 GLuint fb = 0;
9047 glGenFramebuffersEXT(1, &fb);
9048 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9050 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9051 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9052 GL_DEPTH_ATTACHMENT;
9054 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9055 texture->service_id(), level);
9056 // ANGLE promises a depth only attachment ok.
9057 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9058 GL_FRAMEBUFFER_COMPLETE) {
9059 return false;
9061 glClearStencil(0);
9062 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9063 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9064 glClearDepth(1.0f);
9065 state_.SetDeviceDepthMask(GL_TRUE);
9066 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9067 glScissor(xoffset, yoffset, width, height);
9068 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9070 RestoreClearState();
9072 glDeleteFramebuffersEXT(1, &fb);
9073 Framebuffer* framebuffer =
9074 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9075 GLuint fb_service_id =
9076 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9077 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9078 return true;
9081 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9083 uint32 size;
9084 uint32 padded_row_size;
9085 if (!GLES2Util::ComputeImageDataSizes(
9086 width, height, 1, format, type, state_.unpack_alignment, &size,
9087 NULL, &padded_row_size)) {
9088 return false;
9091 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9093 int tile_height;
9095 if (size > kMaxZeroSize) {
9096 if (kMaxZeroSize < padded_row_size) {
9097 // That'd be an awfully large texture.
9098 return false;
9100 // We should never have a large total size with a zero row size.
9101 DCHECK_GT(padded_row_size, 0U);
9102 tile_height = kMaxZeroSize / padded_row_size;
9103 if (!GLES2Util::ComputeImageDataSizes(
9104 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9105 NULL, NULL)) {
9106 return false;
9108 } else {
9109 tile_height = height;
9112 // Assumes the size has already been checked.
9113 scoped_ptr<char[]> zero(new char[size]);
9114 memset(zero.get(), 0, size);
9115 glBindTexture(texture->target(), texture->service_id());
9117 GLint y = 0;
9118 while (y < height) {
9119 GLint h = y + tile_height > height ? height - y : tile_height;
9120 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9121 zero.get());
9122 y += tile_height;
9124 TextureRef* bound_texture =
9125 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9126 glBindTexture(texture->target(),
9127 bound_texture ? bound_texture->service_id() : 0);
9128 return true;
9131 namespace {
9133 const int kS3TCBlockWidth = 4;
9134 const int kS3TCBlockHeight = 4;
9135 const int kS3TCDXT1BlockSize = 8;
9136 const int kS3TCDXT3AndDXT5BlockSize = 16;
9137 const int kEACAndETC2BlockSize = 4;
9139 bool IsValidDXTSize(GLint level, GLsizei size) {
9140 return (size == 1) ||
9141 (size == 2) || !(size % kS3TCBlockWidth);
9144 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9145 return GLES2Util::IsPOT(size);
9148 } // anonymous namespace.
9150 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9151 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9152 GLenum format, GLsizei* size_in_bytes) {
9153 base::CheckedNumeric<GLsizei> bytes_required(0);
9155 switch (format) {
9156 case GL_ATC_RGB_AMD:
9157 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9158 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9159 case GL_ETC1_RGB8_OES:
9160 bytes_required =
9161 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9162 bytes_required *=
9163 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9164 bytes_required *= kS3TCDXT1BlockSize;
9165 break;
9166 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9167 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9168 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9169 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9170 bytes_required =
9171 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9172 bytes_required *=
9173 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9174 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9175 break;
9176 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9177 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9178 bytes_required = std::max(width, 8);
9179 bytes_required *= std::max(height, 8);
9180 bytes_required *= 4;
9181 bytes_required += 7;
9182 bytes_required /= 8;
9183 break;
9184 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9185 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9186 bytes_required = std::max(width, 16);
9187 bytes_required *= std::max(height, 8);
9188 bytes_required *= 2;
9189 bytes_required += 7;
9190 bytes_required /= 8;
9191 break;
9193 // ES3 formats.
9194 case GL_COMPRESSED_R11_EAC:
9195 case GL_COMPRESSED_SIGNED_R11_EAC:
9196 case GL_COMPRESSED_RGB8_ETC2:
9197 case GL_COMPRESSED_SRGB8_ETC2:
9198 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9199 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9200 bytes_required =
9201 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9202 bytes_required *=
9203 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9204 bytes_required *= 8;
9205 bytes_required *= depth;
9206 break;
9207 case GL_COMPRESSED_RG11_EAC:
9208 case GL_COMPRESSED_SIGNED_RG11_EAC:
9209 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9210 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9211 bytes_required =
9212 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9213 bytes_required *=
9214 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9215 bytes_required *= 16;
9216 bytes_required *= depth;
9217 break;
9218 default:
9219 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9220 return false;
9223 if (!bytes_required.IsValid()) {
9224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9225 return false;
9228 *size_in_bytes = bytes_required.ValueOrDefault(0);
9229 return true;
9232 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9233 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9234 GLenum format, GLsizei size) {
9235 GLsizei bytes_required = 0;
9236 if (!GetCompressedTexSizeInBytes(
9237 function_name, width, height, depth, format, &bytes_required)) {
9238 return false;
9241 if (size != bytes_required) {
9242 LOCAL_SET_GL_ERROR(
9243 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9244 return false;
9247 return true;
9250 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9251 const char* function_name, GLenum target, GLint level,
9252 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9253 switch (format) {
9254 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9255 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9256 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9257 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9258 DCHECK_EQ(1, depth); // 2D formats.
9259 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9260 LOCAL_SET_GL_ERROR(
9261 GL_INVALID_OPERATION, function_name,
9262 "width or height invalid for level");
9263 return false;
9265 return true;
9266 case GL_ATC_RGB_AMD:
9267 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9268 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9269 case GL_ETC1_RGB8_OES:
9270 DCHECK_EQ(1, depth); // 2D formats.
9271 if (width <= 0 || height <= 0) {
9272 LOCAL_SET_GL_ERROR(
9273 GL_INVALID_OPERATION, function_name,
9274 "width or height invalid for level");
9275 return false;
9277 return true;
9278 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9279 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9280 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9281 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9282 DCHECK_EQ(1, depth); // 2D formats.
9283 if (!IsValidPVRTCSize(level, width) ||
9284 !IsValidPVRTCSize(level, height)) {
9285 LOCAL_SET_GL_ERROR(
9286 GL_INVALID_OPERATION, function_name,
9287 "width or height invalid for level");
9288 return false;
9290 return true;
9292 // ES3 formats.
9293 case GL_COMPRESSED_R11_EAC:
9294 case GL_COMPRESSED_SIGNED_R11_EAC:
9295 case GL_COMPRESSED_RG11_EAC:
9296 case GL_COMPRESSED_SIGNED_RG11_EAC:
9297 case GL_COMPRESSED_RGB8_ETC2:
9298 case GL_COMPRESSED_SRGB8_ETC2:
9299 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9300 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9301 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9302 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9303 if (width <= 0 || height <= 0 || depth <= 0) {
9304 LOCAL_SET_GL_ERROR(
9305 GL_INVALID_OPERATION, function_name,
9306 "width, height, or depth invalid");
9307 return false;
9309 if (target == GL_TEXTURE_3D) {
9310 LOCAL_SET_GL_ERROR(
9311 GL_INVALID_OPERATION, function_name,
9312 "target invalid for format");
9313 return false;
9315 return true;
9316 default:
9317 return false;
9321 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9322 const char* function_name,
9323 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9324 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9325 Texture* texture) {
9326 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9327 LOCAL_SET_GL_ERROR(
9328 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9329 return false;
9332 switch (format) {
9333 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9334 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9335 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9336 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9337 const int kBlockWidth = 4;
9338 const int kBlockHeight = 4;
9339 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9340 LOCAL_SET_GL_ERROR(
9341 GL_INVALID_OPERATION, function_name,
9342 "xoffset or yoffset not multiple of 4");
9343 return false;
9345 GLsizei tex_width = 0;
9346 GLsizei tex_height = 0;
9347 if (!texture->GetLevelSize(target, level,
9348 &tex_width, &tex_height, nullptr) ||
9349 width - xoffset > tex_width ||
9350 height - yoffset > tex_height) {
9351 LOCAL_SET_GL_ERROR(
9352 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9353 return false;
9355 return ValidateCompressedTexDimensions(
9356 function_name, target, level, width, height, 1, format);
9358 case GL_ATC_RGB_AMD:
9359 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9360 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9361 LOCAL_SET_GL_ERROR(
9362 GL_INVALID_OPERATION, function_name,
9363 "not supported for ATC textures");
9364 return false;
9366 case GL_ETC1_RGB8_OES: {
9367 LOCAL_SET_GL_ERROR(
9368 GL_INVALID_OPERATION, function_name,
9369 "not supported for ECT1_RGB8_OES textures");
9370 return false;
9372 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9373 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9374 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9375 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9376 if ((xoffset != 0) || (yoffset != 0)) {
9377 LOCAL_SET_GL_ERROR(
9378 GL_INVALID_OPERATION, function_name,
9379 "xoffset and yoffset must be zero");
9380 return false;
9382 GLsizei tex_width = 0;
9383 GLsizei tex_height = 0;
9384 if (!texture->GetLevelSize(target, level,
9385 &tex_width, &tex_height, nullptr) ||
9386 width != tex_width ||
9387 height != tex_height) {
9388 LOCAL_SET_GL_ERROR(
9389 GL_INVALID_OPERATION, function_name,
9390 "dimensions must match existing texture level dimensions");
9391 return false;
9393 return ValidateCompressedTexDimensions(
9394 function_name, target, level, width, height, 1, format);
9397 // ES3 formats
9398 case GL_COMPRESSED_R11_EAC:
9399 case GL_COMPRESSED_SIGNED_R11_EAC:
9400 case GL_COMPRESSED_RG11_EAC:
9401 case GL_COMPRESSED_SIGNED_RG11_EAC:
9402 case GL_COMPRESSED_RGB8_ETC2:
9403 case GL_COMPRESSED_SRGB8_ETC2:
9404 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9405 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9406 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9407 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9409 const int kBlockSize = 4;
9410 GLsizei tex_width, tex_height;
9411 if (target == GL_TEXTURE_3D ||
9412 !texture->GetLevelSize(target, level,
9413 &tex_width, &tex_height, nullptr) ||
9414 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9415 ((width % kBlockSize) && xoffset + width != tex_width) ||
9416 ((height % kBlockSize) && yoffset + height != tex_height)) {
9417 LOCAL_SET_GL_ERROR(
9418 GL_INVALID_OPERATION, function_name,
9419 "dimensions must match existing texture level dimensions");
9420 return false;
9422 return true;
9424 default:
9425 return false;
9429 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9430 GLenum target,
9431 GLint level,
9432 GLenum internal_format,
9433 GLsizei width,
9434 GLsizei height,
9435 GLint border,
9436 GLsizei image_size,
9437 const void* data) {
9438 if (!validators_->texture_target.IsValid(target)) {
9439 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9440 "glCompressedTexImage2D", target, "target");
9441 return error::kNoError;
9443 if (!validators_->compressed_texture_format.IsValid(
9444 internal_format)) {
9445 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9446 "glCompressedTexImage2D", internal_format, "internal_format");
9447 return error::kNoError;
9449 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9450 border != 0) {
9451 LOCAL_SET_GL_ERROR(
9452 GL_INVALID_VALUE,
9453 "glCompressedTexImage2D", "dimensions out of range");
9454 return error::kNoError;
9456 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9457 &state_, target);
9458 if (!texture_ref) {
9459 LOCAL_SET_GL_ERROR(
9460 GL_INVALID_VALUE,
9461 "glCompressedTexImage2D", "unknown texture target");
9462 return error::kNoError;
9464 Texture* texture = texture_ref->texture();
9465 if (texture->IsImmutable()) {
9466 LOCAL_SET_GL_ERROR(
9467 GL_INVALID_OPERATION,
9468 "glCompressedTexImage2D", "texture is immutable");
9469 return error::kNoError;
9472 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9473 width, height, 1, internal_format) ||
9474 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9475 1, internal_format, image_size)) {
9476 return error::kNoError;
9479 if (!EnsureGPUMemoryAvailable(image_size)) {
9480 LOCAL_SET_GL_ERROR(
9481 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9482 return error::kNoError;
9485 if (texture->IsAttachedToFramebuffer()) {
9486 framebuffer_state_.clear_state_dirty = true;
9489 scoped_ptr<int8[]> zero;
9490 if (!data) {
9491 zero.reset(new int8[image_size]);
9492 memset(zero.get(), 0, image_size);
9493 data = zero.get();
9495 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9496 glCompressedTexImage2D(
9497 target, level, internal_format, width, height, border, image_size, data);
9498 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9499 if (error == GL_NO_ERROR) {
9500 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9501 width, height, 1, border, 0, 0,
9502 gfx::Rect(width, height));
9505 // This may be a slow command. Exit command processing to allow for
9506 // context preemption and GPU watchdog checks.
9507 ExitCommandProcessingEarly();
9508 return error::kNoError;
9511 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9512 uint32 immediate_data_size,
9513 const void* cmd_data) {
9514 const gles2::cmds::CompressedTexImage2D& c =
9515 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9516 GLenum target = static_cast<GLenum>(c.target);
9517 GLint level = static_cast<GLint>(c.level);
9518 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9519 GLsizei width = static_cast<GLsizei>(c.width);
9520 GLsizei height = static_cast<GLsizei>(c.height);
9521 GLint border = static_cast<GLint>(c.border);
9522 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9523 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9524 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9525 const void* data = NULL;
9526 if (data_shm_id != 0 || data_shm_offset != 0) {
9527 data = GetSharedMemoryAs<const void*>(
9528 data_shm_id, data_shm_offset, image_size);
9529 if (!data) {
9530 return error::kOutOfBounds;
9533 return DoCompressedTexImage2D(
9534 target, level, internal_format, width, height, border, image_size, data);
9537 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9538 uint32 immediate_data_size,
9539 const void* cmd_data) {
9540 const gles2::cmds::CompressedTexImage2DBucket& c =
9541 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9542 GLenum target = static_cast<GLenum>(c.target);
9543 GLint level = static_cast<GLint>(c.level);
9544 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9545 GLsizei width = static_cast<GLsizei>(c.width);
9546 GLsizei height = static_cast<GLsizei>(c.height);
9547 GLint border = static_cast<GLint>(c.border);
9548 Bucket* bucket = GetBucket(c.bucket_id);
9549 if (!bucket) {
9550 return error::kInvalidArguments;
9552 uint32 data_size = bucket->size();
9553 GLsizei imageSize = data_size;
9554 const void* data = bucket->GetData(0, data_size);
9555 if (!data) {
9556 return error::kInvalidArguments;
9558 return DoCompressedTexImage2D(
9559 target, level, internal_format, width, height, border,
9560 imageSize, data);
9563 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9564 uint32 immediate_data_size,
9565 const void* cmd_data) {
9566 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9567 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9568 GLenum target = static_cast<GLenum>(c.target);
9569 GLint level = static_cast<GLint>(c.level);
9570 GLint xoffset = static_cast<GLint>(c.xoffset);
9571 GLint yoffset = static_cast<GLint>(c.yoffset);
9572 GLsizei width = static_cast<GLsizei>(c.width);
9573 GLsizei height = static_cast<GLsizei>(c.height);
9574 GLenum format = static_cast<GLenum>(c.format);
9575 Bucket* bucket = GetBucket(c.bucket_id);
9576 if (!bucket) {
9577 return error::kInvalidArguments;
9579 uint32 data_size = bucket->size();
9580 GLsizei imageSize = data_size;
9581 const void* data = bucket->GetData(0, data_size);
9582 if (!data) {
9583 return error::kInvalidArguments;
9585 if (!validators_->texture_target.IsValid(target)) {
9586 LOCAL_SET_GL_ERROR(
9587 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9588 return error::kNoError;
9590 if (!validators_->compressed_texture_format.IsValid(format)) {
9591 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9592 "glCompressedTexSubImage2D", format, "format");
9593 return error::kNoError;
9595 if (width < 0) {
9596 LOCAL_SET_GL_ERROR(
9597 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9598 return error::kNoError;
9600 if (height < 0) {
9601 LOCAL_SET_GL_ERROR(
9602 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9603 return error::kNoError;
9605 if (imageSize < 0) {
9606 LOCAL_SET_GL_ERROR(
9607 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9608 return error::kNoError;
9610 DoCompressedTexSubImage2D(
9611 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9612 return error::kNoError;
9615 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9616 GLenum target,
9617 GLint level,
9618 GLenum internal_format,
9619 GLsizei width,
9620 GLsizei height,
9621 GLsizei depth,
9622 GLint border,
9623 GLsizei image_size,
9624 const void* data) {
9625 if (!validators_->texture_3_d_target.IsValid(target)) {
9626 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9627 "glCompressedTexImage3D", target, "target");
9628 return error::kNoError;
9630 if (!validators_->compressed_texture_format.IsValid(
9631 internal_format)) {
9632 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9633 "glCompressedTexImage3D", internal_format, "internal_format");
9634 return error::kNoError;
9636 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9637 border != 0) {
9638 LOCAL_SET_GL_ERROR(
9639 GL_INVALID_VALUE,
9640 "glCompressedTexImage3D", "dimensions out of range");
9641 return error::kNoError;
9643 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9644 &state_, target);
9645 if (!texture_ref) {
9646 LOCAL_SET_GL_ERROR(
9647 GL_INVALID_VALUE,
9648 "glCompressedTexImage3D", "unknown texture target");
9649 return error::kNoError;
9651 Texture* texture = texture_ref->texture();
9652 if (texture->IsImmutable()) {
9653 LOCAL_SET_GL_ERROR(
9654 GL_INVALID_OPERATION,
9655 "glCompressedTexImage3D", "texture is immutable");
9656 return error::kNoError;
9659 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9660 width, height, depth, internal_format) ||
9661 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9662 depth, internal_format, image_size)) {
9663 return error::kNoError;
9666 if (!EnsureGPUMemoryAvailable(image_size)) {
9667 LOCAL_SET_GL_ERROR(
9668 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9669 return error::kNoError;
9672 if (texture->IsAttachedToFramebuffer()) {
9673 framebuffer_state_.clear_state_dirty = true;
9676 scoped_ptr<int8[]> zero;
9677 if (!data) {
9678 zero.reset(new int8[image_size]);
9679 memset(zero.get(), 0, image_size);
9680 data = zero.get();
9682 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9683 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9684 border, image_size, data);
9685 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9686 if (error == GL_NO_ERROR) {
9687 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9688 width, height, depth, border, 0, 0,
9689 gfx::Rect(width, height));
9692 // This may be a slow command. Exit command processing to allow for
9693 // context preemption and GPU watchdog checks.
9694 ExitCommandProcessingEarly();
9695 return error::kNoError;
9698 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9699 uint32 immediate_data_size, const void* cmd_data) {
9700 if (!unsafe_es3_apis_enabled())
9701 return error::kUnknownCommand;
9703 const gles2::cmds::CompressedTexImage3D& c =
9704 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9705 GLenum target = static_cast<GLenum>(c.target);
9706 GLint level = static_cast<GLint>(c.level);
9707 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9708 GLsizei width = static_cast<GLsizei>(c.width);
9709 GLsizei height = static_cast<GLsizei>(c.height);
9710 GLsizei depth = static_cast<GLsizei>(c.depth);
9711 GLint border = static_cast<GLint>(c.border);
9712 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9713 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9714 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9715 const void* data = NULL;
9716 if (data_shm_id != 0 || data_shm_offset != 0) {
9717 data = GetSharedMemoryAs<const void*>(
9718 data_shm_id, data_shm_offset, image_size);
9719 if (!data) {
9720 return error::kOutOfBounds;
9723 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9724 depth, border, image_size, data);
9727 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9728 uint32 immediate_data_size, const void* cmd_data) {
9729 if (!unsafe_es3_apis_enabled())
9730 return error::kUnknownCommand;
9732 const gles2::cmds::CompressedTexImage3DBucket& c =
9733 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9734 GLenum target = static_cast<GLenum>(c.target);
9735 GLint level = static_cast<GLint>(c.level);
9736 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9737 GLsizei width = static_cast<GLsizei>(c.width);
9738 GLsizei height = static_cast<GLsizei>(c.height);
9739 GLsizei depth = static_cast<GLsizei>(c.depth);
9740 GLint border = static_cast<GLint>(c.border);
9741 Bucket* bucket = GetBucket(c.bucket_id);
9742 if (!bucket) {
9743 return error::kInvalidArguments;
9745 uint32 data_size = bucket->size();
9746 GLsizei imageSize = data_size;
9747 const void* data = bucket->GetData(0, data_size);
9748 if (!data) {
9749 return error::kInvalidArguments;
9751 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9752 depth, border, imageSize, data);
9755 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9756 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9757 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9758 GLsizei image_size, const void* data) {
9759 if (!validators_->texture_3_d_target.IsValid(target)) {
9760 LOCAL_SET_GL_ERROR(
9761 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9762 return;
9764 if (!validators_->compressed_texture_format.IsValid(format)) {
9765 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9766 "glCompressedTexSubImage3D", format, "format");
9767 return;
9769 if (width < 0 || height < 0 || depth < 0) {
9770 LOCAL_SET_GL_ERROR(
9771 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9772 return;
9774 if (image_size < 0) {
9775 LOCAL_SET_GL_ERROR(
9776 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9777 return;
9779 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9780 &state_, target);
9781 if (!texture_ref) {
9782 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9783 "unknown texture for target");
9784 return;
9786 Texture* texture = texture_ref->texture();
9787 GLenum type = 0, internal_format = 0;
9788 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9789 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9790 "level does not exist");
9791 return;
9793 if (internal_format != format) {
9794 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9795 "format does not match internal format");
9796 return;
9798 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9799 width, height, depth, type)) {
9800 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9801 "bad dimensions");
9802 return;
9804 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9805 width, height, depth, format,
9806 image_size) ||
9807 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9808 target, level, xoffset, yoffset,
9809 zoffset, width, height, depth,
9810 format, texture)) {
9811 return;
9814 // Note: There is no need to deal with texture cleared tracking here
9815 // because the validation above means you can only get here if the level
9816 // is already a matching compressed format and in that case
9817 // CompressedTexImage3D already cleared the texture.
9818 glCompressedTexSubImage3D(
9819 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9820 image_size, data);
9822 // This may be a slow command. Exit command processing to allow for
9823 // context preemption and GPU watchdog checks.
9824 ExitCommandProcessingEarly();
9827 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9828 uint32 immediate_data_size, const void* cmd_data) {
9829 if (!unsafe_es3_apis_enabled())
9830 return error::kUnknownCommand;
9831 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9832 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9833 GLenum target = static_cast<GLenum>(c.target);
9834 GLint level = static_cast<GLint>(c.level);
9835 GLint xoffset = static_cast<GLint>(c.xoffset);
9836 GLint yoffset = static_cast<GLint>(c.yoffset);
9837 GLint zoffset = static_cast<GLint>(c.zoffset);
9838 GLsizei width = static_cast<GLsizei>(c.width);
9839 GLsizei height = static_cast<GLsizei>(c.height);
9840 GLsizei depth = static_cast<GLsizei>(c.depth);
9841 GLenum format = static_cast<GLenum>(c.format);
9842 Bucket* bucket = GetBucket(c.bucket_id);
9843 if (!bucket) {
9844 return error::kInvalidArguments;
9846 uint32 data_size = bucket->size();
9847 GLsizei image_size = data_size;
9848 const void* data = bucket->GetData(0, data_size);
9849 if (!data) {
9850 return error::kInvalidArguments;
9852 DoCompressedTexSubImage3D(
9853 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9854 image_size, data);
9855 return error::kNoError;
9858 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9859 const void* cmd_data) {
9860 const gles2::cmds::TexImage2D& c =
9861 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9862 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9863 "width", c.width, "height", c.height);
9864 // Set as failed for now, but if it successed, this will be set to not failed.
9865 texture_state_.tex_image_failed = true;
9866 GLenum target = static_cast<GLenum>(c.target);
9867 GLint level = static_cast<GLint>(c.level);
9868 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9869 // for internalformat.
9870 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9871 GLsizei width = static_cast<GLsizei>(c.width);
9872 GLsizei height = static_cast<GLsizei>(c.height);
9873 GLint border = static_cast<GLint>(c.border);
9874 GLenum format = static_cast<GLenum>(c.format);
9875 GLenum type = static_cast<GLenum>(c.type);
9876 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9877 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9878 uint32 pixels_size;
9879 if (!GLES2Util::ComputeImageDataSizes(
9880 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9881 NULL, NULL)) {
9882 return error::kOutOfBounds;
9884 const void* pixels = NULL;
9885 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9886 pixels = GetSharedMemoryAs<const void*>(
9887 pixels_shm_id, pixels_shm_offset, pixels_size);
9888 if (!pixels) {
9889 return error::kOutOfBounds;
9893 // For testing only. Allows us to stress the ability to respond to OOM errors.
9894 if (workarounds().simulate_out_of_memory_on_large_textures &&
9895 (width * height >= 4096 * 4096)) {
9896 LOCAL_SET_GL_ERROR(
9897 GL_OUT_OF_MEMORY,
9898 "glTexImage2D", "synthetic out of memory");
9899 return error::kNoError;
9902 TextureManager::DoTexImageArguments args = {
9903 target, level, internal_format, width, height, 1, border, format, type,
9904 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9905 texture_manager()->ValidateAndDoTexImage(
9906 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9908 // This may be a slow command. Exit command processing to allow for
9909 // context preemption and GPU watchdog checks.
9910 ExitCommandProcessingEarly();
9911 return error::kNoError;
9914 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9915 const void* cmd_data) {
9916 if (!unsafe_es3_apis_enabled())
9917 return error::kUnknownCommand;
9919 const gles2::cmds::TexImage3D& c =
9920 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9921 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9922 "widthXheight", c.width * c.height, "depth", c.depth);
9923 // Set as failed for now, but if it successed, this will be set to not failed.
9924 texture_state_.tex_image_failed = true;
9925 GLenum target = static_cast<GLenum>(c.target);
9926 GLint level = static_cast<GLint>(c.level);
9927 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9928 GLsizei width = static_cast<GLsizei>(c.width);
9929 GLsizei height = static_cast<GLsizei>(c.height);
9930 GLsizei depth = static_cast<GLsizei>(c.depth);
9931 GLint border = static_cast<GLint>(c.border);
9932 GLenum format = static_cast<GLenum>(c.format);
9933 GLenum type = static_cast<GLenum>(c.type);
9934 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9935 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9936 uint32 pixels_size;
9937 if (!GLES2Util::ComputeImageDataSizes(
9938 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9939 NULL, NULL)) {
9940 return error::kOutOfBounds;
9942 const void* pixels = NULL;
9943 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9944 pixels = GetSharedMemoryAs<const void*>(
9945 pixels_shm_id, pixels_shm_offset, pixels_size);
9946 if (!pixels) {
9947 return error::kOutOfBounds;
9951 // For testing only. Allows us to stress the ability to respond to OOM errors.
9952 if (workarounds().simulate_out_of_memory_on_large_textures &&
9953 (width * height * depth >= 4096 * 4096)) {
9954 LOCAL_SET_GL_ERROR(
9955 GL_OUT_OF_MEMORY,
9956 "glTexImage3D", "synthetic out of memory");
9957 return error::kNoError;
9960 TextureManager::DoTexImageArguments args = {
9961 target, level, internal_format, width, height, depth, border, format, type,
9962 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
9963 texture_manager()->ValidateAndDoTexImage(
9964 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
9966 // This may be a slow command. Exit command processing to allow for
9967 // context preemption and GPU watchdog checks.
9968 ExitCommandProcessingEarly();
9969 return error::kNoError;
9972 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9973 GLenum target,
9974 GLint level,
9975 GLint xoffset,
9976 GLint yoffset,
9977 GLsizei width,
9978 GLsizei height,
9979 GLenum format,
9980 GLsizei image_size,
9981 const void * data) {
9982 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9983 &state_, target);
9984 if (!texture_ref) {
9985 LOCAL_SET_GL_ERROR(
9986 GL_INVALID_OPERATION,
9987 "glCompressedTexSubImage2D", "unknown texture for target");
9988 return;
9990 Texture* texture = texture_ref->texture();
9991 GLenum type = 0;
9992 GLenum internal_format = 0;
9993 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9994 LOCAL_SET_GL_ERROR(
9995 GL_INVALID_OPERATION,
9996 "glCompressedTexSubImage2D", "level does not exist.");
9997 return;
9999 if (internal_format != format) {
10000 LOCAL_SET_GL_ERROR(
10001 GL_INVALID_OPERATION,
10002 "glCompressedTexSubImage2D", "format does not match internal format.");
10003 return;
10005 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10006 height, 1, type)) {
10007 LOCAL_SET_GL_ERROR(
10008 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10009 return;
10012 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10013 width, height, 1, format, image_size) ||
10014 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10015 target, level, xoffset, yoffset, 0,
10016 width, height, 1, format, texture)) {
10017 return;
10021 // Note: There is no need to deal with texture cleared tracking here
10022 // because the validation above means you can only get here if the level
10023 // is already a matching compressed format and in that case
10024 // CompressedTexImage2D already cleared the texture.
10025 glCompressedTexSubImage2D(
10026 target, level, xoffset, yoffset, width, height, format, image_size, data);
10028 // This may be a slow command. Exit command processing to allow for
10029 // context preemption and GPU watchdog checks.
10030 ExitCommandProcessingEarly();
10033 static void Clip(
10034 GLint start, GLint range, GLint sourceRange,
10035 GLint* out_start, GLint* out_range) {
10036 DCHECK(out_start);
10037 DCHECK(out_range);
10038 if (start < 0) {
10039 range += start;
10040 start = 0;
10042 GLint end = start + range;
10043 if (end > sourceRange) {
10044 range -= end - sourceRange;
10046 *out_start = start;
10047 *out_range = range;
10050 void GLES2DecoderImpl::DoCopyTexImage2D(
10051 GLenum target,
10052 GLint level,
10053 GLenum internal_format,
10054 GLint x,
10055 GLint y,
10056 GLsizei width,
10057 GLsizei height,
10058 GLint border) {
10059 DCHECK(!ShouldDeferReads());
10060 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10061 &state_, target);
10062 if (!texture_ref) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION,
10065 "glCopyTexImage2D", "unknown texture for target");
10066 return;
10068 Texture* texture = texture_ref->texture();
10069 if (texture->IsImmutable()) {
10070 LOCAL_SET_GL_ERROR(
10071 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10072 return;
10074 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10075 border != 0) {
10076 LOCAL_SET_GL_ERROR(
10077 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10078 return;
10080 if (!texture_manager()->ValidateFormatAndTypeCombination(
10081 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10082 GL_UNSIGNED_BYTE)) {
10083 return;
10086 // Check we have compatible formats.
10087 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10088 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10089 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10091 if ((channels_needed & channels_exist) != channels_needed) {
10092 LOCAL_SET_GL_ERROR(
10093 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10094 return;
10097 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10098 LOCAL_SET_GL_ERROR(
10099 GL_INVALID_OPERATION,
10100 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10101 return;
10104 uint32 estimated_size = 0;
10105 if (!GLES2Util::ComputeImageDataSizes(
10106 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10107 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10108 LOCAL_SET_GL_ERROR(
10109 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10110 return;
10113 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10114 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10115 return;
10118 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10119 return;
10122 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10123 LOCAL_SET_GL_ERROR(
10124 GL_INVALID_OPERATION,
10125 "glCopyTexImage2D", "source and destination textures are the same");
10126 return;
10129 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10130 return;
10133 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10134 ScopedResolvedFrameBufferBinder binder(this, false, true);
10135 gfx::Size size = GetBoundReadFrameBufferSize();
10137 if (texture->IsAttachedToFramebuffer()) {
10138 framebuffer_state_.clear_state_dirty = true;
10141 // Clip to size to source dimensions
10142 GLint copyX = 0;
10143 GLint copyY = 0;
10144 GLint copyWidth = 0;
10145 GLint copyHeight = 0;
10146 Clip(x, width, size.width(), &copyX, &copyWidth);
10147 Clip(y, height, size.height(), &copyY, &copyHeight);
10149 if (copyX != x ||
10150 copyY != y ||
10151 copyWidth != width ||
10152 copyHeight != height) {
10153 // some part was clipped so clear the rect.
10154 uint32 pixels_size = 0;
10155 if (!GLES2Util::ComputeImageDataSizes(
10156 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10157 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10158 LOCAL_SET_GL_ERROR(
10159 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10160 return;
10162 scoped_ptr<char[]> zero(new char[pixels_size]);
10163 memset(zero.get(), 0, pixels_size);
10164 ScopedModifyPixels modify(texture_ref);
10165 glTexImage2D(target, level, internal_format, width, height, border,
10166 internal_format, GL_UNSIGNED_BYTE, zero.get());
10167 if (copyHeight > 0 && copyWidth > 0) {
10168 GLint dx = copyX - x;
10169 GLint dy = copyY - y;
10170 GLint destX = dx;
10171 GLint destY = dy;
10172 glCopyTexSubImage2D(target, level,
10173 destX, destY, copyX, copyY,
10174 copyWidth, copyHeight);
10176 } else {
10177 ScopedModifyPixels modify(texture_ref);
10178 glCopyTexImage2D(target, level, internal_format,
10179 copyX, copyY, copyWidth, copyHeight, border);
10181 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10182 if (error == GL_NO_ERROR) {
10183 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10184 width, height, 1, border, internal_format,
10185 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10188 // This may be a slow command. Exit command processing to allow for
10189 // context preemption and GPU watchdog checks.
10190 ExitCommandProcessingEarly();
10193 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10194 GLenum target,
10195 GLint level,
10196 GLint xoffset,
10197 GLint yoffset,
10198 GLint x,
10199 GLint y,
10200 GLsizei width,
10201 GLsizei height) {
10202 DCHECK(!ShouldDeferReads());
10203 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10204 &state_, target);
10205 if (!texture_ref) {
10206 LOCAL_SET_GL_ERROR(
10207 GL_INVALID_OPERATION,
10208 "glCopyTexSubImage2D", "unknown texture for target");
10209 return;
10211 Texture* texture = texture_ref->texture();
10212 GLenum type = 0;
10213 GLenum format = 0;
10214 if (!texture->GetLevelType(target, level, &type, &format) ||
10215 !texture->ValidForTexture(
10216 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10217 LOCAL_SET_GL_ERROR(
10218 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10219 return;
10221 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10222 LOCAL_SET_GL_ERROR(
10223 GL_INVALID_OPERATION,
10224 "glCopyTexSubImage2D", "async upload pending for texture");
10225 return;
10228 // Check we have compatible formats.
10229 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10230 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10231 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10233 if (!channels_needed ||
10234 (channels_needed & channels_exist) != channels_needed) {
10235 LOCAL_SET_GL_ERROR(
10236 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10237 return;
10240 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10241 LOCAL_SET_GL_ERROR(
10242 GL_INVALID_OPERATION,
10243 "glCopySubImage2D", "can not be used with depth or stencil textures");
10244 return;
10247 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10248 return;
10251 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10252 LOCAL_SET_GL_ERROR(
10253 GL_INVALID_OPERATION,
10254 "glCopyTexSubImage2D", "source and destination textures are the same");
10255 return;
10258 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10259 return;
10262 ScopedResolvedFrameBufferBinder binder(this, false, true);
10263 gfx::Size size = GetBoundReadFrameBufferSize();
10264 GLint copyX = 0;
10265 GLint copyY = 0;
10266 GLint copyWidth = 0;
10267 GLint copyHeight = 0;
10268 Clip(x, width, size.width(), &copyX, &copyWidth);
10269 Clip(y, height, size.height(), &copyY, &copyHeight);
10271 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10272 height != size.height()) {
10273 gfx::Rect cleared_rect;
10274 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10275 gfx::Rect(xoffset, yoffset, width, height),
10276 &cleared_rect)) {
10277 DCHECK_GE(cleared_rect.size().GetArea(),
10278 texture->GetLevelClearedRect(target, level).size().GetArea());
10279 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10280 cleared_rect);
10281 } else {
10282 // Otherwise clear part of texture level that is not already cleared.
10283 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10284 level)) {
10285 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10286 "dimensions too big");
10287 return;
10290 } else {
10291 // Write all pixels in below.
10292 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10295 if (copyX != x ||
10296 copyY != y ||
10297 copyWidth != width ||
10298 copyHeight != height) {
10299 // some part was clipped so clear the sub rect.
10300 uint32 pixels_size = 0;
10301 if (!GLES2Util::ComputeImageDataSizes(
10302 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10303 NULL, NULL)) {
10304 LOCAL_SET_GL_ERROR(
10305 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10306 return;
10308 scoped_ptr<char[]> zero(new char[pixels_size]);
10309 memset(zero.get(), 0, pixels_size);
10310 ScopedModifyPixels modify(texture_ref);
10311 glTexSubImage2D(
10312 target, level, xoffset, yoffset, width, height,
10313 format, type, zero.get());
10316 if (copyHeight > 0 && copyWidth > 0) {
10317 GLint dx = copyX - x;
10318 GLint dy = copyY - y;
10319 GLint destX = xoffset + dx;
10320 GLint destY = yoffset + dy;
10321 ScopedModifyPixels modify(texture_ref);
10322 glCopyTexSubImage2D(target, level,
10323 destX, destY, copyX, copyY,
10324 copyWidth, copyHeight);
10327 // This may be a slow command. Exit command processing to allow for
10328 // context preemption and GPU watchdog checks.
10329 ExitCommandProcessingEarly();
10332 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10333 error::Error* error,
10334 const char* function_name,
10335 GLenum target,
10336 GLint level,
10337 GLint xoffset,
10338 GLint yoffset,
10339 GLsizei width,
10340 GLsizei height,
10341 GLenum format,
10342 GLenum type,
10343 const void * data) {
10344 (*error) = error::kNoError;
10345 if (!validators_->texture_target.IsValid(target)) {
10346 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10347 return false;
10349 if (width < 0) {
10350 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10351 return false;
10353 if (height < 0) {
10354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10355 return false;
10357 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10358 &state_, target);
10359 if (!texture_ref) {
10360 LOCAL_SET_GL_ERROR(
10361 GL_INVALID_OPERATION,
10362 function_name, "unknown texture for target");
10363 return false;
10365 Texture* texture = texture_ref->texture();
10366 GLenum current_type = 0;
10367 GLenum internal_format = 0;
10368 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10369 LOCAL_SET_GL_ERROR(
10370 GL_INVALID_OPERATION, function_name, "level does not exist.");
10371 return false;
10373 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10374 function_name, format, type, internal_format, level)) {
10375 return false;
10377 if (type != current_type) {
10378 LOCAL_SET_GL_ERROR(
10379 GL_INVALID_OPERATION,
10380 function_name, "type does not match type of texture.");
10381 return false;
10383 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10384 LOCAL_SET_GL_ERROR(
10385 GL_INVALID_OPERATION,
10386 function_name, "async upload pending for texture");
10387 return false;
10389 if (!texture->ValidForTexture(
10390 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10391 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10392 return false;
10394 if ((GLES2Util::GetChannelsForFormat(format) &
10395 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
10396 && !feature_info_->IsES3Enabled()) {
10397 LOCAL_SET_GL_ERROR(
10398 GL_INVALID_OPERATION,
10399 function_name, "can not supply data for depth or stencil textures");
10400 return false;
10402 if (data == NULL) {
10403 (*error) = error::kOutOfBounds;
10404 return false;
10406 return true;
10409 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10410 GLenum target,
10411 GLint level,
10412 GLint xoffset,
10413 GLint yoffset,
10414 GLsizei width,
10415 GLsizei height,
10416 GLenum format,
10417 GLenum type,
10418 const void * data) {
10419 error::Error error = error::kNoError;
10420 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10421 xoffset, yoffset, width, height, format, type, data)) {
10422 return error;
10424 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10425 &state_, target);
10426 Texture* texture = texture_ref->texture();
10427 GLsizei tex_width = 0;
10428 GLsizei tex_height = 0;
10429 bool ok = texture->GetLevelSize(
10430 target, level, &tex_width, &tex_height, nullptr);
10431 DCHECK(ok);
10432 if (xoffset != 0 || yoffset != 0 ||
10433 width != tex_width || height != tex_height) {
10434 gfx::Rect cleared_rect;
10435 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10436 gfx::Rect(xoffset, yoffset, width, height),
10437 &cleared_rect)) {
10438 DCHECK_GE(cleared_rect.size().GetArea(),
10439 texture->GetLevelClearedRect(target, level).size().GetArea());
10440 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10441 cleared_rect);
10442 } else {
10443 // Otherwise clear part of texture level that is not already cleared.
10444 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10445 level)) {
10446 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
10447 "dimensions too big");
10448 return error::kNoError;
10451 ScopedTextureUploadTimer timer(&texture_state_);
10452 glTexSubImage2D(
10453 target, level, xoffset, yoffset, width, height, format, type, data);
10454 return error::kNoError;
10457 if (!texture_state_.texsubimage_faster_than_teximage &&
10458 !texture->IsImmutable() &&
10459 !texture->HasImages()) {
10460 ScopedTextureUploadTimer timer(&texture_state_);
10461 GLenum internal_format;
10462 GLenum tex_type;
10463 texture->GetLevelType(target, level, &tex_type, &internal_format);
10464 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10465 // to look it up.
10466 glTexImage2D(
10467 target, level, internal_format, width, height, 0, format, type, data);
10468 } else {
10469 ScopedTextureUploadTimer timer(&texture_state_);
10470 glTexSubImage2D(
10471 target, level, xoffset, yoffset, width, height, format, type, data);
10473 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10475 // This may be a slow command. Exit command processing to allow for
10476 // context preemption and GPU watchdog checks.
10477 ExitCommandProcessingEarly();
10478 return error::kNoError;
10481 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10482 const void* cmd_data) {
10483 const gles2::cmds::TexSubImage2D& c =
10484 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10485 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10486 "width", c.width, "height", c.height);
10487 GLboolean internal = static_cast<GLboolean>(c.internal);
10488 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10489 return error::kNoError;
10491 GLenum target = static_cast<GLenum>(c.target);
10492 GLint level = static_cast<GLint>(c.level);
10493 GLint xoffset = static_cast<GLint>(c.xoffset);
10494 GLint yoffset = static_cast<GLint>(c.yoffset);
10495 GLsizei width = static_cast<GLsizei>(c.width);
10496 GLsizei height = static_cast<GLsizei>(c.height);
10497 GLenum format = static_cast<GLenum>(c.format);
10498 GLenum type = static_cast<GLenum>(c.type);
10499 uint32 data_size;
10500 if (!GLES2Util::ComputeImageDataSizes(
10501 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10502 NULL, NULL)) {
10503 return error::kOutOfBounds;
10505 const void* pixels = GetSharedMemoryAs<const void*>(
10506 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10507 return DoTexSubImage2D(
10508 target, level, xoffset, yoffset, width, height, format, type, pixels);
10511 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10512 GLenum target,
10513 GLint level,
10514 GLint xoffset,
10515 GLint yoffset,
10516 GLint zoffset,
10517 GLsizei width,
10518 GLsizei height,
10519 GLsizei depth,
10520 GLenum format,
10521 GLenum type,
10522 const void * data) {
10523 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10524 &state_, target);
10525 if (!texture_ref) {
10526 LOCAL_SET_GL_ERROR(
10527 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10530 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10531 ScopedTextureUploadTimer timer(&texture_state_);
10532 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10533 depth, format, type, data);
10534 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10535 if (error == GL_NO_ERROR) {
10536 // TODO(zmo): This is not 100% correct because only part of the level
10537 // image is cleared.
10538 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10541 // This may be a slow command. Exit command processing to allow for
10542 // context preemption and GPU watchdog checks.
10543 ExitCommandProcessingEarly();
10544 return error::kNoError;
10547 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10548 const void* cmd_data) {
10549 if (!unsafe_es3_apis_enabled())
10550 return error::kUnknownCommand;
10552 const gles2::cmds::TexSubImage3D& c =
10553 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10554 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10555 "widthXheight", c.width * c.height, "depth", c.depth);
10556 GLboolean internal = static_cast<GLboolean>(c.internal);
10557 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10558 return error::kNoError;
10560 GLenum target = static_cast<GLenum>(c.target);
10561 GLint level = static_cast<GLint>(c.level);
10562 GLint xoffset = static_cast<GLint>(c.xoffset);
10563 GLint yoffset = static_cast<GLint>(c.yoffset);
10564 GLint zoffset = static_cast<GLint>(c.zoffset);
10565 GLsizei width = static_cast<GLsizei>(c.width);
10566 GLsizei height = static_cast<GLsizei>(c.height);
10567 GLsizei depth = static_cast<GLsizei>(c.depth);
10568 GLenum format = static_cast<GLenum>(c.format);
10569 GLenum type = static_cast<GLenum>(c.type);
10570 uint32 data_size;
10571 if (!GLES2Util::ComputeImageDataSizes(
10572 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10573 NULL, NULL)) {
10574 return error::kOutOfBounds;
10576 const void* pixels = GetSharedMemoryAs<const void*>(
10577 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10578 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10579 height, depth, format, type, pixels);
10582 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10583 uint32 immediate_data_size,
10584 const void* cmd_data) {
10585 const gles2::cmds::GetVertexAttribPointerv& c =
10586 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10587 GLuint index = static_cast<GLuint>(c.index);
10588 GLenum pname = static_cast<GLenum>(c.pname);
10589 typedef cmds::GetVertexAttribPointerv::Result Result;
10590 Result* result = GetSharedMemoryAs<Result*>(
10591 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10592 if (!result) {
10593 return error::kOutOfBounds;
10595 // Check that the client initialized the result.
10596 if (result->size != 0) {
10597 return error::kInvalidArguments;
10599 if (!validators_->vertex_pointer.IsValid(pname)) {
10600 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10601 "glGetVertexAttribPointerv", pname, "pname");
10602 return error::kNoError;
10604 if (index >= group_->max_vertex_attribs()) {
10605 LOCAL_SET_GL_ERROR(
10606 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10607 return error::kNoError;
10609 result->SetNumResults(1);
10610 *result->GetData() =
10611 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10612 return error::kNoError;
10615 template <class T>
10616 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10617 GLint fake_location,
10618 uint32 shm_id,
10619 uint32 shm_offset,
10620 error::Error* error,
10621 GLint* real_location,
10622 GLuint* service_id,
10623 SizedResult<T>** result_pointer,
10624 GLenum* result_type,
10625 GLsizei* result_size) {
10626 DCHECK(error);
10627 DCHECK(service_id);
10628 DCHECK(result_pointer);
10629 DCHECK(result_type);
10630 DCHECK(result_size);
10631 DCHECK(real_location);
10632 *error = error::kNoError;
10633 // Make sure we have enough room for the result on failure.
10634 SizedResult<T>* result;
10635 result = GetSharedMemoryAs<SizedResult<T>*>(
10636 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10637 if (!result) {
10638 *error = error::kOutOfBounds;
10639 return false;
10641 *result_pointer = result;
10642 // Set the result size to 0 so the client does not have to check for success.
10643 result->SetNumResults(0);
10644 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10645 if (!program) {
10646 return false;
10648 if (!program->IsValid()) {
10649 // Program was not linked successfully. (ie, glLinkProgram)
10650 LOCAL_SET_GL_ERROR(
10651 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10652 return false;
10654 *service_id = program->service_id();
10655 GLint array_index = -1;
10656 const Program::UniformInfo* uniform_info =
10657 program->GetUniformInfoByFakeLocation(
10658 fake_location, real_location, &array_index);
10659 if (!uniform_info) {
10660 // No such location.
10661 LOCAL_SET_GL_ERROR(
10662 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10663 return false;
10665 GLenum type = uniform_info->type;
10666 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10667 if (num_elements == 0) {
10668 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10669 return false;
10671 result = GetSharedMemoryAs<SizedResult<T>*>(
10672 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10673 if (!result) {
10674 *error = error::kOutOfBounds;
10675 return false;
10677 result->SetNumResults(num_elements);
10678 *result_size = num_elements * sizeof(T);
10679 *result_type = type;
10680 return true;
10683 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10684 const void* cmd_data) {
10685 const gles2::cmds::GetUniformiv& c =
10686 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10687 GLuint program = c.program;
10688 GLint fake_location = c.location;
10689 GLuint service_id;
10690 GLenum result_type;
10691 GLsizei result_size;
10692 GLint real_location = -1;
10693 Error error;
10694 cmds::GetUniformiv::Result* result;
10695 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10696 c.params_shm_offset, &error, &real_location,
10697 &service_id, &result, &result_type,
10698 &result_size)) {
10699 glGetUniformiv(
10700 service_id, real_location, result->GetData());
10702 return error;
10705 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10706 const void* cmd_data) {
10707 if (!unsafe_es3_apis_enabled())
10708 return error::kUnknownCommand;
10710 const gles2::cmds::GetUniformuiv& c =
10711 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10712 GLuint program = c.program;
10713 GLint fake_location = c.location;
10714 GLuint service_id;
10715 GLenum result_type;
10716 GLsizei result_size;
10717 GLint real_location = -1;
10718 Error error;
10719 cmds::GetUniformuiv::Result* result;
10720 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10721 c.params_shm_offset, &error, &real_location,
10722 &service_id, &result, &result_type,
10723 &result_size)) {
10724 glGetUniformuiv(
10725 service_id, real_location, result->GetData());
10727 return error;
10730 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10731 const void* cmd_data) {
10732 const gles2::cmds::GetUniformfv& c =
10733 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10734 GLuint program = c.program;
10735 GLint fake_location = c.location;
10736 GLuint service_id;
10737 GLint real_location = -1;
10738 Error error;
10739 cmds::GetUniformfv::Result* result;
10740 GLenum result_type;
10741 GLsizei result_size;
10742 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10743 c.params_shm_offset, &error, &real_location,
10744 &service_id, &result, &result_type,
10745 &result_size)) {
10746 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10747 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10748 GLsizei num_values = result_size / sizeof(GLfloat);
10749 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10750 glGetUniformiv(service_id, real_location, temp.get());
10751 GLfloat* dst = result->GetData();
10752 for (GLsizei ii = 0; ii < num_values; ++ii) {
10753 dst[ii] = (temp[ii] != 0);
10755 } else {
10756 glGetUniformfv(service_id, real_location, result->GetData());
10759 return error;
10762 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10763 uint32 immediate_data_size,
10764 const void* cmd_data) {
10765 const gles2::cmds::GetShaderPrecisionFormat& c =
10766 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10767 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10768 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10769 typedef cmds::GetShaderPrecisionFormat::Result Result;
10770 Result* result = GetSharedMemoryAs<Result*>(
10771 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10772 if (!result) {
10773 return error::kOutOfBounds;
10775 // Check that the client initialized the result.
10776 if (result->success != 0) {
10777 return error::kInvalidArguments;
10779 if (!validators_->shader_type.IsValid(shader_type)) {
10780 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10781 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10782 return error::kNoError;
10784 if (!validators_->shader_precision.IsValid(precision_type)) {
10785 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10786 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10787 return error::kNoError;
10790 result->success = 1; // true
10792 GLint range[2] = { 0, 0 };
10793 GLint precision = 0;
10794 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10796 result->min_range = range[0];
10797 result->max_range = range[1];
10798 result->precision = precision;
10800 return error::kNoError;
10803 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10804 uint32 immediate_data_size,
10805 const void* cmd_data) {
10806 const gles2::cmds::GetAttachedShaders& c =
10807 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10808 uint32 result_size = c.result_size;
10809 GLuint program_id = static_cast<GLuint>(c.program);
10810 Program* program = GetProgramInfoNotShader(
10811 program_id, "glGetAttachedShaders");
10812 if (!program) {
10813 return error::kNoError;
10815 typedef cmds::GetAttachedShaders::Result Result;
10816 uint32 max_count = Result::ComputeMaxResults(result_size);
10817 Result* result = GetSharedMemoryAs<Result*>(
10818 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10819 if (!result) {
10820 return error::kOutOfBounds;
10822 // Check that the client initialized the result.
10823 if (result->size != 0) {
10824 return error::kInvalidArguments;
10826 GLsizei count = 0;
10827 glGetAttachedShaders(
10828 program->service_id(), max_count, &count, result->GetData());
10829 for (GLsizei ii = 0; ii < count; ++ii) {
10830 if (!shader_manager()->GetClientId(result->GetData()[ii],
10831 &result->GetData()[ii])) {
10832 NOTREACHED();
10833 return error::kGenericError;
10836 result->SetNumResults(count);
10837 return error::kNoError;
10840 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10841 uint32 immediate_data_size,
10842 const void* cmd_data) {
10843 const gles2::cmds::GetActiveUniform& c =
10844 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10845 GLuint program_id = c.program;
10846 GLuint index = c.index;
10847 uint32 name_bucket_id = c.name_bucket_id;
10848 typedef cmds::GetActiveUniform::Result Result;
10849 Result* result = GetSharedMemoryAs<Result*>(
10850 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10851 if (!result) {
10852 return error::kOutOfBounds;
10854 // Check that the client initialized the result.
10855 if (result->success != 0) {
10856 return error::kInvalidArguments;
10858 Program* program = GetProgramInfoNotShader(
10859 program_id, "glGetActiveUniform");
10860 if (!program) {
10861 return error::kNoError;
10863 const Program::UniformInfo* uniform_info =
10864 program->GetUniformInfo(index);
10865 if (!uniform_info) {
10866 LOCAL_SET_GL_ERROR(
10867 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10868 return error::kNoError;
10870 result->success = 1; // true.
10871 result->size = uniform_info->size;
10872 result->type = uniform_info->type;
10873 Bucket* bucket = CreateBucket(name_bucket_id);
10874 bucket->SetFromString(uniform_info->name.c_str());
10875 return error::kNoError;
10878 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10879 uint32 immediate_data_size, const void* cmd_data) {
10880 if (!unsafe_es3_apis_enabled())
10881 return error::kUnknownCommand;
10882 const gles2::cmds::GetActiveUniformBlockiv& c =
10883 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10884 GLuint program_id = c.program;
10885 GLuint index = static_cast<GLuint>(c.index);
10886 GLenum pname = static_cast<GLenum>(c.pname);
10887 Program* program = GetProgramInfoNotShader(
10888 program_id, "glGetActiveUniformBlockiv");
10889 if (!program) {
10890 return error::kNoError;
10892 GLuint service_id = program->service_id();
10893 GLint link_status = GL_FALSE;
10894 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10895 if (link_status != GL_TRUE) {
10896 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10897 "glGetActiveActiveUniformBlockiv", "program not linked");
10898 return error::kNoError;
10900 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10901 GLsizei num_values = 1;
10902 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10903 GLint num = 0;
10904 glGetActiveUniformBlockiv(
10905 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10906 GLenum error = glGetError();
10907 if (error != GL_NO_ERROR) {
10908 // Assume this will the same error if calling with pname.
10909 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10910 return error::kNoError;
10912 num_values = static_cast<GLsizei>(num);
10914 typedef cmds::GetActiveUniformBlockiv::Result Result;
10915 Result* result = GetSharedMemoryAs<Result*>(
10916 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10917 GLint* params = result ? result->GetData() : NULL;
10918 if (params == NULL) {
10919 return error::kOutOfBounds;
10921 // Check that the client initialized the result.
10922 if (result->size != 0) {
10923 return error::kInvalidArguments;
10925 glGetActiveUniformBlockiv(service_id, index, pname, params);
10926 GLenum error = glGetError();
10927 if (error == GL_NO_ERROR) {
10928 result->SetNumResults(num_values);
10929 } else {
10930 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10932 return error::kNoError;
10935 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10936 uint32 immediate_data_size, const void* cmd_data) {
10937 if (!unsafe_es3_apis_enabled())
10938 return error::kUnknownCommand;
10939 const gles2::cmds::GetActiveUniformBlockName& c =
10940 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10941 GLuint program_id = c.program;
10942 GLuint index = c.index;
10943 uint32 name_bucket_id = c.name_bucket_id;
10944 typedef cmds::GetActiveUniformBlockName::Result Result;
10945 Result* result = GetSharedMemoryAs<Result*>(
10946 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10947 if (!result) {
10948 return error::kOutOfBounds;
10950 // Check that the client initialized the result.
10951 if (*result != 0) {
10952 return error::kInvalidArguments;
10954 Program* program = GetProgramInfoNotShader(
10955 program_id, "glGetActiveUniformBlockName");
10956 if (!program) {
10957 return error::kNoError;
10959 GLuint service_id = program->service_id();
10960 GLint link_status = GL_FALSE;
10961 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10962 if (link_status != GL_TRUE) {
10963 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10964 "glGetActiveActiveUniformBlockName", "program not linked");
10965 return error::kNoError;
10967 GLint max_length = 0;
10968 glGetProgramiv(
10969 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10970 // Increase one so &buffer[0] is always valid.
10971 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10972 std::vector<char> buffer(buf_size);
10973 GLsizei length = 0;
10974 glGetActiveUniformBlockName(
10975 service_id, index, buf_size, &length, &buffer[0]);
10976 if (length == 0) {
10977 *result = 0;
10978 return error::kNoError;
10980 *result = 1;
10981 Bucket* bucket = CreateBucket(name_bucket_id);
10982 DCHECK_GT(buf_size, length);
10983 DCHECK_EQ(0, buffer[length]);
10984 bucket->SetFromString(&buffer[0]);
10985 return error::kNoError;
10988 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10989 uint32 immediate_data_size, const void* cmd_data) {
10990 if (!unsafe_es3_apis_enabled())
10991 return error::kUnknownCommand;
10992 const gles2::cmds::GetActiveUniformsiv& c =
10993 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10994 GLuint program_id = c.program;
10995 GLenum pname = static_cast<GLenum>(c.pname);
10996 Bucket* bucket = GetBucket(c.indices_bucket_id);
10997 if (!bucket) {
10998 return error::kInvalidArguments;
11000 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11001 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11002 typedef cmds::GetActiveUniformsiv::Result Result;
11003 Result* result = GetSharedMemoryAs<Result*>(
11004 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11005 GLint* params = result ? result->GetData() : NULL;
11006 if (params == NULL) {
11007 return error::kOutOfBounds;
11009 // Check that the client initialized the result.
11010 if (result->size != 0) {
11011 return error::kInvalidArguments;
11013 Program* program = GetProgramInfoNotShader(
11014 program_id, "glGetActiveUniformsiv");
11015 if (!program) {
11016 return error::kNoError;
11018 GLuint service_id = program->service_id();
11019 GLint link_status = GL_FALSE;
11020 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11021 if (link_status != GL_TRUE) {
11022 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11023 "glGetActiveUniformsiv", "program not linked");
11024 return error::kNoError;
11026 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11027 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11028 GLenum error = glGetError();
11029 if (error == GL_NO_ERROR) {
11030 result->SetNumResults(count);
11031 } else {
11032 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11034 return error::kNoError;
11037 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11038 const void* cmd_data) {
11039 const gles2::cmds::GetActiveAttrib& c =
11040 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11041 GLuint program_id = c.program;
11042 GLuint index = c.index;
11043 uint32 name_bucket_id = c.name_bucket_id;
11044 typedef cmds::GetActiveAttrib::Result Result;
11045 Result* result = GetSharedMemoryAs<Result*>(
11046 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11047 if (!result) {
11048 return error::kOutOfBounds;
11050 // Check that the client initialized the result.
11051 if (result->success != 0) {
11052 return error::kInvalidArguments;
11054 Program* program = GetProgramInfoNotShader(
11055 program_id, "glGetActiveAttrib");
11056 if (!program) {
11057 return error::kNoError;
11059 const Program::VertexAttrib* attrib_info =
11060 program->GetAttribInfo(index);
11061 if (!attrib_info) {
11062 LOCAL_SET_GL_ERROR(
11063 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11064 return error::kNoError;
11066 result->success = 1; // true.
11067 result->size = attrib_info->size;
11068 result->type = attrib_info->type;
11069 Bucket* bucket = CreateBucket(name_bucket_id);
11070 bucket->SetFromString(attrib_info->name.c_str());
11071 return error::kNoError;
11074 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11075 const void* cmd_data) {
11076 #if 1 // No binary shader support.
11077 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11078 return error::kNoError;
11079 #else
11080 GLsizei n = static_cast<GLsizei>(c.n);
11081 if (n < 0) {
11082 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11083 return error::kNoError;
11085 GLsizei length = static_cast<GLsizei>(c.length);
11086 if (length < 0) {
11087 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11088 return error::kNoError;
11090 uint32 data_size;
11091 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11092 return error::kOutOfBounds;
11094 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11095 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11096 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11097 const void* binary = GetSharedMemoryAs<const void*>(
11098 c.binary_shm_id, c.binary_shm_offset, length);
11099 if (shaders == NULL || binary == NULL) {
11100 return error::kOutOfBounds;
11102 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11103 for (GLsizei ii = 0; ii < n; ++ii) {
11104 Shader* shader = GetShader(shaders[ii]);
11105 if (!shader) {
11106 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11107 return error::kNoError;
11109 service_ids[ii] = shader->service_id();
11111 // TODO(gman): call glShaderBinary
11112 return error::kNoError;
11113 #endif
11116 void GLES2DecoderImpl::DoSwapBuffers() {
11117 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11119 int this_frame_number = frame_number_++;
11120 // TRACE_EVENT for gpu tests:
11121 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11122 TRACE_EVENT_SCOPE_THREAD,
11123 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11124 "width", (is_offscreen ? offscreen_size_.width() :
11125 surface_->GetSize().width()));
11126 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11127 "offscreen", is_offscreen,
11128 "frame", this_frame_number);
11130 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11133 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11134 "GLES2Decoder", "SwapBuffer");
11136 bool is_tracing;
11137 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11138 &is_tracing);
11139 if (is_tracing) {
11140 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11141 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11142 is_offscreen ? offscreen_size_ : surface_->GetSize());
11145 // If offscreen then don't actually SwapBuffers to the display. Just copy
11146 // the rendered frame to another frame buffer.
11147 if (is_offscreen) {
11148 TRACE_EVENT2("gpu", "Offscreen",
11149 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11150 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11151 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11152 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11153 // fix this.
11154 if (workarounds().needs_offscreen_buffer_workaround) {
11155 offscreen_saved_frame_buffer_->Create();
11156 glFinish();
11159 // Allocate the offscreen saved color texture.
11160 DCHECK(offscreen_saved_color_format_);
11161 offscreen_saved_color_texture_->AllocateStorage(
11162 offscreen_size_, offscreen_saved_color_format_, false);
11164 offscreen_saved_frame_buffer_->AttachRenderTexture(
11165 offscreen_saved_color_texture_.get());
11166 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11167 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11168 GL_FRAMEBUFFER_COMPLETE) {
11169 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11170 << "because offscreen saved FBO was incomplete.";
11171 MarkContextLost(error::kUnknown);
11172 group_->LoseContexts(error::kUnknown);
11173 return;
11176 // Clear the offscreen color texture.
11177 // TODO(piman): Is this still necessary?
11179 ScopedFrameBufferBinder binder(this,
11180 offscreen_saved_frame_buffer_->id());
11181 glClearColor(0, 0, 0, 0);
11182 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11183 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11184 glClear(GL_COLOR_BUFFER_BIT);
11185 RestoreClearState();
11189 UpdateParentTextureInfo();
11192 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11193 return;
11194 ScopedGLErrorSuppressor suppressor(
11195 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11197 if (IsOffscreenBufferMultisampled()) {
11198 // For multisampled buffers, resolve the frame buffer.
11199 ScopedResolvedFrameBufferBinder binder(this, true, false);
11200 } else {
11201 ScopedFrameBufferBinder binder(this,
11202 offscreen_target_frame_buffer_->id());
11204 if (offscreen_target_buffer_preserved_) {
11205 // Copy the target frame buffer to the saved offscreen texture.
11206 offscreen_saved_color_texture_->Copy(
11207 offscreen_saved_color_texture_->size(),
11208 offscreen_saved_color_format_);
11209 } else {
11210 // Flip the textures in the parent context via the texture manager.
11211 if (!!offscreen_saved_color_texture_info_.get())
11212 offscreen_saved_color_texture_info_->texture()->
11213 SetServiceId(offscreen_target_color_texture_->id());
11215 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11216 offscreen_target_frame_buffer_->AttachRenderTexture(
11217 offscreen_target_color_texture_.get());
11220 // Ensure the side effects of the copy are visible to the parent
11221 // context. There is no need to do this for ANGLE because it uses a
11222 // single D3D device for all contexts.
11223 if (!feature_info_->gl_version_info().is_angle)
11224 glFlush();
11226 } else {
11227 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11228 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11229 if (!CheckResetStatus()) {
11230 MarkContextLost(error::kUnknown);
11231 group_->LoseContexts(error::kUnknown);
11236 // This may be a slow command. Exit command processing to allow for
11237 // context preemption and GPU watchdog checks.
11238 ExitCommandProcessingEarly();
11241 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11242 context_->SetSwapInterval(interval);
11245 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11246 uint32 immediate_data_size,
11247 const void* cmd_data) {
11248 const gles2::cmds::EnableFeatureCHROMIUM& c =
11249 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11250 Bucket* bucket = GetBucket(c.bucket_id);
11251 if (!bucket || bucket->size() == 0) {
11252 return error::kInvalidArguments;
11254 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11255 Result* result = GetSharedMemoryAs<Result*>(
11256 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11257 if (!result) {
11258 return error::kOutOfBounds;
11260 // Check that the client initialized the result.
11261 if (*result != 0) {
11262 return error::kInvalidArguments;
11264 std::string feature_str;
11265 if (!bucket->GetAsString(&feature_str)) {
11266 return error::kInvalidArguments;
11269 // TODO(gman): make this some kind of table to function pointer thingy.
11270 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11271 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11272 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11273 buffer_manager()->set_allow_fixed_attribs(true);
11274 // TODO(gman): decide how to remove the need for this const_cast.
11275 // I could make validators_ non const but that seems bad as this is the only
11276 // place it is needed. I could make some special friend class of validators
11277 // just to allow this to set them. That seems silly. I could refactor this
11278 // code to use the extension mechanism or the initialization attributes to
11279 // turn this feature on. Given that the only real point of this is to make
11280 // the conformance tests pass and given that there is lots of real work that
11281 // needs to be done it seems like refactoring for one to one of those
11282 // methods is a very low priority.
11283 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11284 } else {
11285 return error::kNoError;
11288 *result = 1; // true.
11289 return error::kNoError;
11292 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11293 uint32 immediate_data_size,
11294 const void* cmd_data) {
11295 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11296 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11297 cmd_data);
11298 Bucket* bucket = CreateBucket(c.bucket_id);
11299 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11300 info->Initialize(disallowed_features_);
11301 bucket->SetFromString(info->extensions().c_str());
11302 return error::kNoError;
11305 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11306 uint32 immediate_data_size,
11307 const void* cmd_data) {
11308 const gles2::cmds::RequestExtensionCHROMIUM& c =
11309 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11310 Bucket* bucket = GetBucket(c.bucket_id);
11311 if (!bucket || bucket->size() == 0) {
11312 return error::kInvalidArguments;
11314 std::string feature_str;
11315 if (!bucket->GetAsString(&feature_str)) {
11316 return error::kInvalidArguments;
11319 bool desire_standard_derivatives = false;
11320 bool desire_frag_depth = false;
11321 bool desire_draw_buffers = false;
11322 bool desire_shader_texture_lod = false;
11323 if (IsWebGLContext()) {
11324 desire_standard_derivatives =
11325 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11326 desire_frag_depth =
11327 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11328 desire_draw_buffers =
11329 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11330 desire_shader_texture_lod =
11331 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11334 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11335 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11336 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11337 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11338 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11339 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11340 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11341 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11342 InitializeShaderTranslator();
11345 UpdateCapabilities();
11347 return error::kNoError;
11350 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11351 uint32 immediate_data_size,
11352 const void* cmd_data) {
11353 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11354 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11355 GLuint program_id = static_cast<GLuint>(c.program);
11356 uint32 bucket_id = c.bucket_id;
11357 Bucket* bucket = CreateBucket(bucket_id);
11358 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11359 Program* program = NULL;
11360 program = GetProgram(program_id);
11361 if (!program || !program->IsValid()) {
11362 return error::kNoError;
11364 program->GetProgramInfo(program_manager(), bucket);
11365 return error::kNoError;
11368 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11369 uint32 immediate_data_size, const void* cmd_data) {
11370 if (!unsafe_es3_apis_enabled())
11371 return error::kUnknownCommand;
11372 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11373 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11374 GLuint program_id = static_cast<GLuint>(c.program);
11375 uint32 bucket_id = c.bucket_id;
11376 Bucket* bucket = CreateBucket(bucket_id);
11377 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11378 Program* program = NULL;
11379 program = GetProgram(program_id);
11380 if (!program || !program->IsValid()) {
11381 return error::kNoError;
11383 program->GetUniformBlocks(bucket);
11384 return error::kNoError;
11387 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11388 uint32 immediate_data_size, const void* cmd_data) {
11389 if (!unsafe_es3_apis_enabled())
11390 return error::kUnknownCommand;
11391 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11392 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11393 GLuint program_id = static_cast<GLuint>(c.program);
11394 uint32 bucket_id = c.bucket_id;
11395 Bucket* bucket = CreateBucket(bucket_id);
11396 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11397 Program* program = NULL;
11398 program = GetProgram(program_id);
11399 if (!program || !program->IsValid()) {
11400 return error::kNoError;
11402 program->GetUniformsES3(bucket);
11403 return error::kNoError;
11406 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11407 uint32 immediate_data_size,
11408 const void* cmd_data) {
11409 if (!unsafe_es3_apis_enabled())
11410 return error::kUnknownCommand;
11411 const gles2::cmds::GetTransformFeedbackVarying& c =
11412 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11413 GLuint program_id = c.program;
11414 GLuint index = c.index;
11415 uint32 name_bucket_id = c.name_bucket_id;
11416 typedef cmds::GetTransformFeedbackVarying::Result Result;
11417 Result* result = GetSharedMemoryAs<Result*>(
11418 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11419 if (!result) {
11420 return error::kOutOfBounds;
11422 // Check that the client initialized the result.
11423 if (result->success != 0) {
11424 return error::kInvalidArguments;
11426 Program* program = GetProgramInfoNotShader(
11427 program_id, "glGetTransformFeedbackVarying");
11428 if (!program) {
11429 return error::kNoError;
11431 GLuint service_id = program->service_id();
11432 GLint link_status = GL_FALSE;
11433 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11434 if (link_status != GL_TRUE) {
11435 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11436 "glGetTransformFeedbackVarying", "program not linked");
11437 return error::kNoError;
11439 GLint max_length = 0;
11440 glGetProgramiv(
11441 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11442 max_length = std::max(1, max_length);
11443 std::vector<char> buffer(max_length);
11444 GLsizei length = 0;
11445 GLsizei size = 0;
11446 GLenum type = 0;
11447 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11448 glGetTransformFeedbackVarying(
11449 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11450 GLenum error = glGetError();
11451 if (error != GL_NO_ERROR) {
11452 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11453 return error::kNoError;
11455 result->success = 1; // true.
11456 result->size = static_cast<int32_t>(size);
11457 result->type = static_cast<uint32_t>(type);
11458 Bucket* bucket = CreateBucket(name_bucket_id);
11459 DCHECK(length >= 0 && length < max_length);
11460 buffer[length] = '\0'; // Just to be safe.
11461 bucket->SetFromString(&buffer[0]);
11462 return error::kNoError;
11465 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11466 uint32 immediate_data_size, const void* cmd_data) {
11467 if (!unsafe_es3_apis_enabled())
11468 return error::kUnknownCommand;
11469 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11470 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11471 cmd_data);
11472 GLuint program_id = static_cast<GLuint>(c.program);
11473 uint32 bucket_id = c.bucket_id;
11474 Bucket* bucket = CreateBucket(bucket_id);
11475 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11476 Program* program = NULL;
11477 program = GetProgram(program_id);
11478 if (!program || !program->IsValid()) {
11479 return error::kNoError;
11481 program->GetTransformFeedbackVaryings(bucket);
11482 return error::kNoError;
11485 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11486 return context_lost_reason_;
11489 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11490 GLenum reset_status) const {
11491 switch (reset_status) {
11492 case GL_NO_ERROR:
11493 // TODO(kbr): improve the precision of the error code in this case.
11494 // Consider delegating to context for error code if MakeCurrent fails.
11495 return error::kUnknown;
11496 case GL_GUILTY_CONTEXT_RESET_ARB:
11497 return error::kGuilty;
11498 case GL_INNOCENT_CONTEXT_RESET_ARB:
11499 return error::kInnocent;
11500 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11501 return error::kUnknown;
11504 NOTREACHED();
11505 return error::kUnknown;
11508 bool GLES2DecoderImpl::WasContextLost() const {
11509 return context_was_lost_;
11512 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11513 return WasContextLost() && reset_by_robustness_extension_;
11516 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11517 // Only lose the context once.
11518 if (WasContextLost())
11519 return;
11521 // Don't make GL calls in here, the context might not be current.
11522 context_lost_reason_ = reason;
11523 current_decoder_error_ = error::kLostContext;
11524 context_was_lost_ = true;
11527 bool GLES2DecoderImpl::CheckResetStatus() {
11528 DCHECK(!WasContextLost());
11529 DCHECK(context_->IsCurrent(NULL));
11531 if (IsRobustnessSupported()) {
11532 // If the reason for the call was a GL error, we can try to determine the
11533 // reset status more accurately.
11534 GLenum driver_status = glGetGraphicsResetStatusARB();
11535 if (driver_status == GL_NO_ERROR)
11536 return false;
11538 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11539 << " context lost via ARB/EXT_robustness. Reset status = "
11540 << GLES2Util::GetStringEnum(driver_status);
11542 // Don't pretend we know which client was responsible.
11543 if (workarounds().use_virtualized_gl_contexts)
11544 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11546 switch (driver_status) {
11547 case GL_GUILTY_CONTEXT_RESET_ARB:
11548 MarkContextLost(error::kGuilty);
11549 break;
11550 case GL_INNOCENT_CONTEXT_RESET_ARB:
11551 MarkContextLost(error::kInnocent);
11552 break;
11553 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11554 MarkContextLost(error::kUnknown);
11555 break;
11556 default:
11557 NOTREACHED();
11558 return false;
11560 reset_by_robustness_extension_ = true;
11561 return true;
11563 return false;
11566 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11567 uint32 immediate_data_size,
11568 const void* cmd_data) {
11569 return error::kUnknownCommand;
11572 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11573 uint32 immediate_data_size,
11574 const void* cmd_data) {
11575 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11576 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11577 uint32 sync_point = c.sync_point;
11578 if (wait_sync_point_callback_.is_null())
11579 return error::kNoError;
11581 return wait_sync_point_callback_.Run(sync_point) ?
11582 error::kNoError : error::kDeferCommandUntilLater;
11585 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11586 uint32 immediate_data_size,
11587 const void* cmd_data) {
11588 if (surface_->DeferDraws())
11589 return error::kDeferCommandUntilLater;
11590 if (!surface_->SetBackbufferAllocation(false))
11591 return error::kLostContext;
11592 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11593 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11594 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11595 return error::kNoError;
11598 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11599 GLsizei n, const GLuint* client_ids) {
11600 for (GLsizei ii = 0; ii < n; ++ii) {
11601 if (query_manager_->GetQuery(client_ids[ii])) {
11602 return false;
11605 query_manager_->GenQueries(n, client_ids);
11606 return true;
11609 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11610 GLsizei n, const GLuint* client_ids) {
11611 for (GLsizei ii = 0; ii < n; ++ii) {
11612 query_manager_->RemoveQuery(client_ids[ii]);
11616 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11617 if (query_manager_.get() == NULL) {
11618 return false;
11620 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11621 current_decoder_error_ = error::kOutOfBounds;
11623 return query_manager_->HavePendingQueries();
11626 // Note that if there are no pending readpixels right now,
11627 // this function will call the callback immediately.
11628 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11629 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11630 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11631 } else {
11632 callback.Run();
11636 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
11637 // Note: |did_finish| guarantees that the GPU has passed the fence but
11638 // we cannot assume that GLFence::HasCompleted() will return true yet as
11639 // that's not guaranteed by all GLFence implementations.
11640 while (!pending_readpixel_fences_.empty() &&
11641 (did_finish ||
11642 pending_readpixel_fences_.front()->fence->HasCompleted())) {
11643 std::vector<base::Closure> callbacks =
11644 pending_readpixel_fences_.front()->callbacks;
11645 pending_readpixel_fences_.pop();
11646 for (size_t i = 0; i < callbacks.size(); i++) {
11647 callbacks[i].Run();
11652 bool GLES2DecoderImpl::HasMoreIdleWork() {
11653 return !pending_readpixel_fences_.empty() ||
11654 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11657 void GLES2DecoderImpl::PerformIdleWork() {
11658 ProcessPendingReadPixels(false);
11659 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11660 return;
11661 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11662 ProcessFinishedAsyncTransfers();
11665 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11666 const void* cmd_data) {
11667 const gles2::cmds::BeginQueryEXT& c =
11668 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11669 GLenum target = static_cast<GLenum>(c.target);
11670 GLuint client_id = static_cast<GLuint>(c.id);
11671 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11672 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11674 switch (target) {
11675 case GL_COMMANDS_ISSUED_CHROMIUM:
11676 case GL_LATENCY_QUERY_CHROMIUM:
11677 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11678 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11679 case GL_GET_ERROR_QUERY_CHROMIUM:
11680 break;
11681 case GL_COMMANDS_COMPLETED_CHROMIUM:
11682 if (!features().chromium_sync_query) {
11683 LOCAL_SET_GL_ERROR(
11684 GL_INVALID_OPERATION, "glBeginQueryEXT",
11685 "not enabled for commands completed queries");
11686 return error::kNoError;
11688 break;
11689 case GL_SAMPLES_PASSED:
11690 case GL_ANY_SAMPLES_PASSED:
11691 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
11692 if (!features().occlusion_query_boolean) {
11693 LOCAL_SET_GL_ERROR(
11694 GL_INVALID_OPERATION, "glBeginQueryEXT",
11695 "not enabled for occlusion queries");
11696 return error::kNoError;
11698 break;
11699 case GL_TIME_ELAPSED:
11700 if (!query_manager_->GPUTimingAvailable()) {
11701 LOCAL_SET_GL_ERROR(
11702 GL_INVALID_OPERATION, "glBeginQueryEXT",
11703 "not enabled for timing queries");
11704 return error::kNoError;
11706 break;
11707 default:
11708 LOCAL_SET_GL_ERROR(
11709 GL_INVALID_ENUM, "glBeginQueryEXT",
11710 "unknown query target");
11711 return error::kNoError;
11714 if (query_manager_->GetActiveQuery(target)) {
11715 LOCAL_SET_GL_ERROR(
11716 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11717 return error::kNoError;
11720 if (client_id == 0) {
11721 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11722 return error::kNoError;
11725 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11726 if (!query) {
11727 if (!query_manager_->IsValidQuery(client_id)) {
11728 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11729 "glBeginQueryEXT",
11730 "id not made by glGenQueriesEXT");
11731 return error::kNoError;
11733 query = query_manager_->CreateQuery(
11734 target, client_id, sync_shm_id, sync_shm_offset);
11737 if (query->target() != target) {
11738 LOCAL_SET_GL_ERROR(
11739 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11740 return error::kNoError;
11741 } else if (query->shm_id() != sync_shm_id ||
11742 query->shm_offset() != sync_shm_offset) {
11743 DLOG(ERROR) << "Shared memory used by query not the same as before";
11744 return error::kInvalidArguments;
11747 if (!query_manager_->BeginQuery(query)) {
11748 return error::kOutOfBounds;
11751 return error::kNoError;
11754 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11755 const void* cmd_data) {
11756 const gles2::cmds::EndQueryEXT& c =
11757 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11758 GLenum target = static_cast<GLenum>(c.target);
11759 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11761 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
11762 if (!query) {
11763 LOCAL_SET_GL_ERROR(
11764 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11765 return error::kNoError;
11768 if (!query_manager_->EndQuery(query, submit_count)) {
11769 return error::kOutOfBounds;
11772 query_manager_->ProcessPendingTransferQueries();
11774 return error::kNoError;
11777 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
11778 const void* cmd_data) {
11779 const gles2::cmds::QueryCounterEXT& c =
11780 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
11781 GLuint client_id = static_cast<GLuint>(c.id);
11782 GLenum target = static_cast<GLenum>(c.target);
11783 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11784 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11785 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11787 switch (target) {
11788 case GL_TIMESTAMP:
11789 if (!query_manager_->GPUTimingAvailable()) {
11790 LOCAL_SET_GL_ERROR(
11791 GL_INVALID_OPERATION, "glQueryCounterEXT",
11792 "not enabled for timing queries");
11793 return error::kNoError;
11795 break;
11796 default:
11797 LOCAL_SET_GL_ERROR(
11798 GL_INVALID_ENUM, "glQueryCounterEXT",
11799 "unknown query target");
11800 return error::kNoError;
11803 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11804 if (!query) {
11805 if (!query_manager_->IsValidQuery(client_id)) {
11806 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11807 "glQueryCounterEXT",
11808 "id not made by glGenQueriesEXT");
11809 return error::kNoError;
11811 query = query_manager_->CreateQuery(
11812 target, client_id, sync_shm_id, sync_shm_offset);
11814 if (!query_manager_->QueryCounter(query, submit_count)) {
11815 return error::kOutOfBounds;
11818 return error::kNoError;
11821 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11822 GLsizei n, const GLuint* client_ids) {
11823 for (GLsizei ii = 0; ii < n; ++ii) {
11824 if (GetVertexAttribManager(client_ids[ii])) {
11825 return false;
11829 if (!features().native_vertex_array_object) {
11830 // Emulated VAO
11831 for (GLsizei ii = 0; ii < n; ++ii) {
11832 CreateVertexAttribManager(client_ids[ii], 0, true);
11834 } else {
11835 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11837 glGenVertexArraysOES(n, service_ids.get());
11838 for (GLsizei ii = 0; ii < n; ++ii) {
11839 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11843 return true;
11846 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11847 GLsizei n, const GLuint* client_ids) {
11848 for (GLsizei ii = 0; ii < n; ++ii) {
11849 VertexAttribManager* vao =
11850 GetVertexAttribManager(client_ids[ii]);
11851 if (vao && !vao->IsDeleted()) {
11852 if (state_.vertex_attrib_manager.get() == vao) {
11853 DoBindVertexArrayOES(0);
11855 RemoveVertexAttribManager(client_ids[ii]);
11860 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11861 VertexAttribManager* vao = NULL;
11862 if (client_id != 0) {
11863 vao = GetVertexAttribManager(client_id);
11864 if (!vao) {
11865 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11866 // only allows names that have been previously generated. As such, we do
11867 // not generate new names here.
11868 LOCAL_SET_GL_ERROR(
11869 GL_INVALID_OPERATION,
11870 "glBindVertexArrayOES", "bad vertex array id.");
11871 current_decoder_error_ = error::kNoError;
11872 return;
11874 } else {
11875 vao = state_.default_vertex_attrib_manager.get();
11878 // Only set the VAO state if it's changed
11879 if (state_.vertex_attrib_manager.get() != vao) {
11880 state_.vertex_attrib_manager = vao;
11881 if (!features().native_vertex_array_object) {
11882 EmulateVertexArrayState();
11883 } else {
11884 GLuint service_id = vao->service_id();
11885 glBindVertexArrayOES(service_id);
11890 // Used when OES_vertex_array_object isn't natively supported
11891 void GLES2DecoderImpl::EmulateVertexArrayState() {
11892 // Setup the Vertex attribute state
11893 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11894 RestoreStateForAttrib(vv, true);
11897 // Setup the element buffer
11898 Buffer* element_array_buffer =
11899 state_.vertex_attrib_manager->element_array_buffer();
11900 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11901 element_array_buffer ? element_array_buffer->service_id() : 0);
11904 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11905 const VertexAttribManager* vao =
11906 GetVertexAttribManager(client_id);
11907 return vao && vao->IsValid() && !vao->IsDeleted();
11910 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
11911 GLuint service_id = 0;
11912 return path_manager()->GetPath(client_id, &service_id) &&
11913 glIsPathNV(service_id) == GL_TRUE;
11916 #if defined(OS_MACOSX)
11917 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
11918 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
11919 texture_id);
11920 if (it != texture_to_io_surface_map_.end()) {
11921 // Found a previous IOSurface bound to this texture; release it.
11922 IOSurfaceRef surface = it->second;
11923 CFRelease(surface);
11924 texture_to_io_surface_map_.erase(it);
11927 #endif
11929 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11930 GLenum target, GLsizei width, GLsizei height,
11931 GLuint io_surface_id, GLuint plane) {
11932 #if defined(OS_MACOSX)
11933 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
11934 LOCAL_SET_GL_ERROR(
11935 GL_INVALID_OPERATION,
11936 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11937 return;
11940 if (target != GL_TEXTURE_RECTANGLE_ARB) {
11941 // This might be supported in the future, and if we could require
11942 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11943 // could delete a lot of code. For now, perform strict validation so we
11944 // know what's going on.
11945 LOCAL_SET_GL_ERROR(
11946 GL_INVALID_OPERATION,
11947 "glTexImageIOSurface2DCHROMIUM",
11948 "requires TEXTURE_RECTANGLE_ARB target");
11949 return;
11952 // Default target might be conceptually valid, but disallow it to avoid
11953 // accidents.
11954 TextureRef* texture_ref =
11955 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11956 if (!texture_ref) {
11957 LOCAL_SET_GL_ERROR(
11958 GL_INVALID_OPERATION,
11959 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11960 return;
11963 // Look up the new IOSurface. Note that because of asynchrony
11964 // between processes this might fail; during live resizing the
11965 // plugin process might allocate and release an IOSurface before
11966 // this process gets a chance to look it up. Hold on to any old
11967 // IOSurface in this case.
11968 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11969 if (!surface) {
11970 LOCAL_SET_GL_ERROR(
11971 GL_INVALID_OPERATION,
11972 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11973 return;
11976 // Release any IOSurface previously bound to this texture.
11977 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11979 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11980 texture_to_io_surface_map_.insert(
11981 std::make_pair(texture_ref->service_id(), surface));
11983 CGLContextObj context =
11984 static_cast<CGLContextObj>(context_->GetHandle());
11986 CGLError err = CGLTexImageIOSurface2D(
11987 context,
11988 target,
11989 GL_RGBA,
11990 width,
11991 height,
11992 GL_BGRA,
11993 GL_UNSIGNED_INT_8_8_8_8_REV,
11994 surface,
11995 plane);
11997 if (err != kCGLNoError) {
11998 LOCAL_SET_GL_ERROR(
11999 GL_INVALID_OPERATION,
12000 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12001 return;
12004 texture_manager()->SetLevelInfo(
12005 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12006 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12008 #else
12009 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12010 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12011 #endif
12014 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12015 switch (internalformat) {
12016 case GL_R8:
12017 case GL_R8_SNORM:
12018 case GL_R16F:
12019 case GL_R32F:
12020 return GL_RED;
12021 case GL_R8UI:
12022 case GL_R8I:
12023 case GL_R16UI:
12024 case GL_R16I:
12025 case GL_R32UI:
12026 case GL_R32I:
12027 return GL_RED_INTEGER;
12028 case GL_RG8:
12029 case GL_RG8_SNORM:
12030 case GL_RG16F:
12031 case GL_RG32F:
12032 return GL_RG;
12033 case GL_RG8UI:
12034 case GL_RG8I:
12035 case GL_RG16UI:
12036 case GL_RG16I:
12037 case GL_RG32UI:
12038 case GL_RG32I:
12039 return GL_RG_INTEGER;
12040 case GL_ATC_RGB_AMD:
12041 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12042 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12043 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12044 case GL_ETC1_RGB8_OES:
12045 case GL_RGB8:
12046 case GL_R11F_G11F_B10F:
12047 case GL_RGB565:
12048 case GL_RGB8_SNORM:
12049 case GL_RGB9_E5:
12050 case GL_RGB16F:
12051 case GL_RGB32F:
12052 return GL_RGB;
12053 case GL_RGB8UI:
12054 case GL_RGB8I:
12055 case GL_RGB16UI:
12056 case GL_RGB16I:
12057 case GL_RGB32UI:
12058 case GL_RGB32I:
12059 return GL_RGB_INTEGER;
12060 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12061 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12062 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12063 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12064 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12065 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12066 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12067 case GL_RGBA8:
12068 case GL_SRGB8_ALPHA8:
12069 case GL_RGBA8_SNORM:
12070 case GL_RGBA4:
12071 case GL_RGB5_A1:
12072 case GL_RGB10_A2:
12073 case GL_RGBA16F:
12074 case GL_RGBA32F:
12075 return GL_RGBA;
12076 case GL_RGBA8UI:
12077 case GL_RGBA8I:
12078 case GL_RGB10_A2UI:
12079 case GL_RGBA16UI:
12080 case GL_RGBA16I:
12081 case GL_RGBA32UI:
12082 case GL_RGBA32I:
12083 return GL_RGBA_INTEGER;
12084 case GL_DEPTH_COMPONENT16:
12085 case GL_DEPTH_COMPONENT24:
12086 case GL_DEPTH_COMPONENT32F:
12087 return GL_DEPTH_COMPONENT;
12088 case GL_DEPTH24_STENCIL8:
12089 case GL_DEPTH32F_STENCIL8:
12090 return GL_DEPTH_STENCIL;
12091 case GL_LUMINANCE8_ALPHA8_EXT:
12092 return GL_LUMINANCE_ALPHA;
12093 case GL_LUMINANCE8_EXT:
12094 return GL_LUMINANCE;
12095 case GL_ALPHA8_EXT:
12096 return GL_ALPHA;
12097 case GL_ALPHA32F_EXT:
12098 return GL_ALPHA;
12099 case GL_LUMINANCE32F_EXT:
12100 return GL_LUMINANCE;
12101 case GL_LUMINANCE_ALPHA32F_EXT:
12102 return GL_LUMINANCE_ALPHA;
12103 case GL_ALPHA16F_EXT:
12104 return GL_ALPHA;
12105 case GL_LUMINANCE16F_EXT:
12106 return GL_LUMINANCE;
12107 case GL_LUMINANCE_ALPHA16F_EXT:
12108 return GL_LUMINANCE_ALPHA;
12109 case GL_BGRA8_EXT:
12110 return GL_BGRA_EXT;
12111 default:
12112 return GL_NONE;
12116 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12117 const char* function_name,
12118 GLenum target,
12119 TextureRef* source_texture_ref,
12120 TextureRef* dest_texture_ref,
12121 GLenum dest_internal_format) {
12122 if (!source_texture_ref || !dest_texture_ref) {
12123 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12124 return false;
12127 if (GL_TEXTURE_2D != target) {
12128 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12129 "invalid texture target");
12130 return false;
12133 Texture* source_texture = source_texture_ref->texture();
12134 Texture* dest_texture = dest_texture_ref->texture();
12135 if (source_texture == dest_texture) {
12136 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12137 "source and destination textures are the same");
12138 return false;
12141 if (dest_texture->target() != GL_TEXTURE_2D ||
12142 (source_texture->target() != GL_TEXTURE_2D &&
12143 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12144 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12145 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12146 "invalid texture target binding");
12147 return false;
12150 GLenum source_type = 0;
12151 GLenum source_internal_format = 0;
12152 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12153 &source_internal_format);
12155 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12156 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12157 // renderable on some platforms.
12158 bool valid_dest_format = dest_internal_format == GL_RGB ||
12159 dest_internal_format == GL_RGBA ||
12160 dest_internal_format == GL_BGRA_EXT;
12161 bool valid_source_format =
12162 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12163 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12164 source_internal_format == GL_LUMINANCE ||
12165 source_internal_format == GL_LUMINANCE_ALPHA ||
12166 source_internal_format == GL_BGRA_EXT;
12167 if (!valid_source_format || !valid_dest_format) {
12168 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12169 "invalid internal format");
12170 return false;
12172 return true;
12175 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12176 const char* function_name,
12177 GLenum target,
12178 TextureRef* source_texture_ref,
12179 TextureRef* dest_texture_ref) {
12180 if (!source_texture_ref || !dest_texture_ref) {
12181 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12182 return false;
12185 if (GL_TEXTURE_2D != target) {
12186 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12187 "invalid texture target");
12188 return false;
12191 Texture* source_texture = source_texture_ref->texture();
12192 Texture* dest_texture = dest_texture_ref->texture();
12193 if (source_texture == dest_texture) {
12194 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12195 "source and destination textures are the same");
12196 return false;
12199 if (dest_texture->target() != GL_TEXTURE_2D ||
12200 (source_texture->target() != GL_TEXTURE_2D &&
12201 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12202 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12203 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12204 "invalid texture target binding");
12205 return false;
12208 GLenum source_type = 0;
12209 GLenum source_internal_format = 0;
12210 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12211 &source_internal_format);
12213 bool valid_format =
12214 source_internal_format == GL_ATC_RGB_AMD ||
12215 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12216 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12217 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12218 source_internal_format == GL_ETC1_RGB8_OES;
12220 if (!valid_format) {
12221 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12222 "invalid internal format");
12223 return false;
12226 return true;
12229 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12230 GLenum target,
12231 GLuint source_id,
12232 GLuint dest_id,
12233 GLenum internal_format,
12234 GLenum dest_type,
12235 GLboolean unpack_flip_y,
12236 GLboolean unpack_premultiply_alpha,
12237 GLboolean unpack_unmultiply_alpha) {
12238 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12240 TextureRef* source_texture_ref = GetTexture(source_id);
12241 TextureRef* dest_texture_ref = GetTexture(dest_id);
12242 Texture* source_texture = source_texture_ref->texture();
12243 Texture* dest_texture = dest_texture_ref->texture();
12244 int source_width = 0;
12245 int source_height = 0;
12246 gfx::GLImage* image =
12247 source_texture->GetLevelImage(source_texture->target(), 0);
12248 if (image) {
12249 gfx::Size size = image->GetSize();
12250 source_width = size.width();
12251 source_height = size.height();
12252 if (source_width <= 0 || source_height <= 0) {
12253 LOCAL_SET_GL_ERROR(
12254 GL_INVALID_VALUE,
12255 "glCopyTextureChromium", "invalid image size");
12256 return;
12258 } else {
12259 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12260 &source_width, &source_height, nullptr)) {
12261 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12262 "glCopyTextureChromium",
12263 "source texture has no level 0");
12264 return;
12267 // Check that this type of texture is allowed.
12268 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12269 source_width, source_height, 1)) {
12270 LOCAL_SET_GL_ERROR(
12271 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12272 return;
12276 GLenum source_type = 0;
12277 GLenum source_internal_format = 0;
12278 source_texture->GetLevelType(
12279 source_texture->target(), 0, &source_type, &source_internal_format);
12281 if (dest_texture->IsImmutable()) {
12282 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12283 "texture is immutable");
12284 return;
12287 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12288 source_texture_ref, dest_texture_ref,
12289 internal_format)) {
12290 return;
12293 // Clear the source texture if necessary.
12294 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12295 source_texture->target(), 0)) {
12296 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12297 "dimensions too big");
12298 return;
12301 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12302 // needed because it takes 10s of milliseconds to initialize.
12303 if (!copy_texture_CHROMIUM_.get()) {
12304 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12305 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12306 copy_texture_CHROMIUM_->Initialize(this);
12307 RestoreCurrentFramebufferBindings();
12308 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12309 return;
12312 GLenum dest_type_previous = dest_type;
12313 GLenum dest_internal_format = internal_format;
12314 int dest_width = 0;
12315 int dest_height = 0;
12316 bool dest_level_defined = dest_texture->GetLevelSize(
12317 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12319 if (dest_level_defined) {
12320 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12321 &dest_internal_format);
12324 // Resize the destination texture to the dimensions of the source texture.
12325 if (!dest_level_defined || dest_width != source_width ||
12326 dest_height != source_height ||
12327 dest_internal_format != internal_format ||
12328 dest_type_previous != dest_type) {
12329 // Ensure that the glTexImage2D succeeds.
12330 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12331 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12332 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12333 0, internal_format, dest_type, NULL);
12334 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12335 if (error != GL_NO_ERROR) {
12336 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12337 return;
12340 texture_manager()->SetLevelInfo(
12341 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12342 source_height, 1, 0, internal_format, dest_type,
12343 gfx::Rect(source_width, source_height));
12344 } else {
12345 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12346 true);
12349 ScopedModifyPixels modify(dest_texture_ref);
12351 // Try using GLImage::CopyTexSubImage when possible.
12352 bool unpack_premultiply_alpha_change =
12353 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12354 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12355 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12356 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12357 gfx::Rect(0, 0, source_width, source_height))) {
12358 return;
12362 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12364 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12365 // before presenting.
12366 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12367 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12368 // instead of using kIdentityMatrix crbug.com/226218.
12369 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12370 this, source_texture->target(), source_texture->service_id(),
12371 dest_texture->service_id(), source_width, source_height,
12372 unpack_flip_y == GL_TRUE,
12373 unpack_premultiply_alpha == GL_TRUE,
12374 unpack_unmultiply_alpha == GL_TRUE,
12375 kIdentityMatrix);
12376 } else {
12377 copy_texture_CHROMIUM_->DoCopyTexture(
12378 this, source_texture->target(), source_texture->service_id(),
12379 source_internal_format, dest_texture->service_id(), internal_format,
12380 source_width, source_height,
12381 unpack_flip_y == GL_TRUE,
12382 unpack_premultiply_alpha == GL_TRUE,
12383 unpack_unmultiply_alpha == GL_TRUE);
12386 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12389 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12390 GLenum target,
12391 GLuint source_id,
12392 GLuint dest_id,
12393 GLint xoffset,
12394 GLint yoffset,
12395 GLint x,
12396 GLint y,
12397 GLsizei width,
12398 GLsizei height,
12399 GLboolean unpack_flip_y,
12400 GLboolean unpack_premultiply_alpha,
12401 GLboolean unpack_unmultiply_alpha) {
12402 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12404 TextureRef* source_texture_ref = GetTexture(source_id);
12405 TextureRef* dest_texture_ref = GetTexture(dest_id);
12406 Texture* source_texture = source_texture_ref->texture();
12407 Texture* dest_texture = dest_texture_ref->texture();
12408 int source_width = 0;
12409 int source_height = 0;
12410 gfx::GLImage* image =
12411 source_texture->GetLevelImage(source_texture->target(), 0);
12412 if (image) {
12413 gfx::Size size = image->GetSize();
12414 source_width = size.width();
12415 source_height = size.height();
12416 if (source_width <= 0 || source_height <= 0) {
12417 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12418 "invalid image size");
12419 return;
12421 } else {
12422 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12423 &source_width, &source_height, nullptr)) {
12424 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12425 "source texture has no level 0");
12426 return;
12429 // Check that this type of texture is allowed.
12430 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12431 source_width, source_height, 1)) {
12432 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12433 "source texture bad dimensions");
12434 return;
12438 GLenum source_type = 0;
12439 GLenum source_internal_format = 0;
12440 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12441 &source_internal_format);
12442 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12443 width, height, 1, source_type)) {
12444 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12445 "source texture bad dimensions.");
12446 return;
12449 GLenum dest_type = 0;
12450 GLenum dest_internal_format = 0;
12451 bool dest_level_defined = dest_texture->GetLevelType(
12452 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12453 if (!dest_level_defined) {
12454 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12455 "destination texture is not defined");
12456 return;
12458 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12459 yoffset, 0, width, height, 1, dest_type)) {
12460 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12461 "destination texture bad dimensions.");
12462 return;
12465 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12466 source_texture_ref, dest_texture_ref,
12467 dest_internal_format)) {
12468 return;
12471 // Clear the source texture if necessary.
12472 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12473 source_texture->target(), 0)) {
12474 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12475 "source texture dimensions too big");
12476 return;
12479 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12480 // needed because it takes 10s of milliseconds to initialize.
12481 if (!copy_texture_CHROMIUM_.get()) {
12482 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12483 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12484 copy_texture_CHROMIUM_->Initialize(this);
12485 RestoreCurrentFramebufferBindings();
12486 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12487 return;
12490 int dest_width = 0;
12491 int dest_height = 0;
12492 bool ok = dest_texture->GetLevelSize(
12493 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12494 DCHECK(ok);
12495 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12496 height != dest_height) {
12497 gfx::Rect cleared_rect;
12498 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12499 gfx::Rect(xoffset, yoffset, width, height),
12500 &cleared_rect)) {
12501 DCHECK_GE(cleared_rect.size().GetArea(),
12502 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12503 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12504 cleared_rect);
12505 } else {
12506 // Otherwise clear part of texture level that is not already cleared.
12507 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12508 0)) {
12509 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12510 "destination texture dimensions too big");
12511 return;
12514 } else {
12515 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12516 true);
12519 ScopedModifyPixels modify(dest_texture_ref);
12521 // Try using GLImage::CopyTexSubImage when possible.
12522 bool unpack_premultiply_alpha_change =
12523 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12524 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12525 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12526 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12527 gfx::Rect(x, y, width, height))) {
12528 return;
12532 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12534 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12535 // crbug.com/226218.
12536 copy_texture_CHROMIUM_->DoCopySubTexture(
12537 this, source_texture->target(), source_texture->service_id(),
12538 source_internal_format, dest_texture->service_id(), dest_internal_format,
12539 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12540 source_width, source_height,
12541 unpack_flip_y == GL_TRUE,
12542 unpack_premultiply_alpha == GL_TRUE,
12543 unpack_unmultiply_alpha == GL_TRUE);
12545 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12548 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
12549 GLuint source_id,
12550 GLuint dest_id) {
12551 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12553 TextureRef* source_texture_ref = GetTexture(source_id);
12554 TextureRef* dest_texture_ref = GetTexture(dest_id);
12555 Texture* source_texture = source_texture_ref->texture();
12556 Texture* dest_texture = dest_texture_ref->texture();
12557 int source_width = 0;
12558 int source_height = 0;
12559 gfx::GLImage* image =
12560 source_texture->GetLevelImage(source_texture->target(), 0);
12561 if (image) {
12562 gfx::Size size = image->GetSize();
12563 source_width = size.width();
12564 source_height = size.height();
12565 if (source_width <= 0 || source_height <= 0) {
12566 LOCAL_SET_GL_ERROR(
12567 GL_INVALID_VALUE,
12568 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12569 return;
12571 } else {
12572 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12573 &source_width, &source_height, nullptr)) {
12574 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12575 "glCompressedCopyTextureCHROMIUM",
12576 "source texture has no level 0");
12577 return;
12580 // Check that this type of texture is allowed.
12581 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12582 source_width, source_height, 1)) {
12583 LOCAL_SET_GL_ERROR(
12584 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
12585 "Bad dimensions");
12586 return;
12590 GLenum source_type = 0;
12591 GLenum source_internal_format = 0;
12592 source_texture->GetLevelType(
12593 source_texture->target(), 0, &source_type, &source_internal_format);
12595 if (dest_texture->IsImmutable()) {
12596 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12597 "glCompressedCopyTextureCHROMIUM",
12598 "texture is immutable");
12599 return;
12602 if (!ValidateCompressedCopyTextureCHROMIUM(
12603 "glCompressedCopyTextureCHROMIUM",
12604 target,
12605 source_texture_ref, dest_texture_ref)) {
12606 return;
12609 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12610 // needed because it takes 10s of milliseconds to initialize.
12611 if (!copy_texture_CHROMIUM_.get()) {
12612 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12613 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12614 copy_texture_CHROMIUM_->Initialize(this);
12615 RestoreCurrentFramebufferBindings();
12616 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12617 return;
12620 // Clear the source texture if necessary.
12621 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12622 source_texture->target(), 0)) {
12623 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
12624 "dimensions too big");
12625 return;
12628 ScopedTextureBinder binder(
12629 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12631 ScopedModifyPixels modify(dest_texture_ref);
12633 // Try using GLImage::CopyTexImage when possible.
12634 if (image) {
12635 GLenum dest_type = 0;
12636 GLenum dest_internal_format = 0;
12637 int dest_width = 0;
12638 int dest_height = 0;
12639 bool dest_level_defined = dest_texture->GetLevelSize(
12640 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12642 if (dest_level_defined) {
12643 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
12644 &dest_internal_format);
12647 // Resize the destination texture to the dimensions of the source texture.
12648 if (!dest_level_defined || dest_width != source_width ||
12649 dest_height != source_height ||
12650 dest_internal_format != source_internal_format) {
12651 GLsizei source_size = 0;
12653 bool did_get_size = GetCompressedTexSizeInBytes(
12654 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
12655 1, source_internal_format, &source_size);
12656 DCHECK(did_get_size);
12658 // Ensure that the glCompressedTexImage2D succeeds.
12659 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12660 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
12661 source_width, source_height, 0, source_size,
12662 NULL);
12663 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12664 if (error != GL_NO_ERROR) {
12665 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12666 return;
12669 texture_manager()->SetLevelInfo(
12670 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
12671 source_width, source_height, 1, 0, source_internal_format,
12672 source_type, gfx::Rect(source_width, source_height));
12673 } else {
12674 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12675 true);
12678 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12679 gfx::Rect(0, 0, source_width, source_height))) {
12680 return;
12684 TRACE_EVENT0(
12685 "gpu",
12686 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12688 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12690 // As a fallback, copy into a non-compressed GL_RGBA texture.
12691 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12692 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
12693 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12694 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12695 if (error != GL_NO_ERROR) {
12696 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12697 return;
12700 texture_manager()->SetLevelInfo(
12701 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
12702 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12703 gfx::Rect(source_width, source_height));
12705 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12706 // before presenting.
12707 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12708 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12709 // instead of using kIdentityMatrix crbug.com/226218.
12710 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12711 this, source_texture->target(), source_texture->service_id(),
12712 dest_texture->service_id(), source_width, source_height,
12713 false, false, false, kIdentityMatrix);
12714 } else {
12715 copy_texture_CHROMIUM_->DoCopyTexture(
12716 this, source_texture->target(), source_texture->service_id(),
12717 source_internal_format, dest_texture->service_id(), GL_RGBA,
12718 source_width, source_height, false, false, false);
12721 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12724 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
12725 switch (internalformat) {
12726 case GL_R8:
12727 return GL_UNSIGNED_BYTE;
12728 case GL_R8_SNORM:
12729 return GL_BYTE;
12730 case GL_R16F:
12731 return GL_HALF_FLOAT;
12732 case GL_R32F:
12733 return GL_FLOAT;
12734 case GL_R8UI:
12735 return GL_UNSIGNED_BYTE;
12736 case GL_R8I:
12737 return GL_BYTE;
12738 case GL_R16UI:
12739 return GL_UNSIGNED_SHORT;
12740 case GL_R16I:
12741 return GL_SHORT;
12742 case GL_R32UI:
12743 return GL_UNSIGNED_INT;
12744 case GL_R32I:
12745 return GL_INT;
12746 case GL_RG8:
12747 return GL_UNSIGNED_BYTE;
12748 case GL_RG8_SNORM:
12749 return GL_BYTE;
12750 case GL_RG16F:
12751 return GL_HALF_FLOAT;
12752 case GL_RG32F:
12753 return GL_FLOAT;
12754 case GL_RG8UI:
12755 return GL_UNSIGNED_BYTE;
12756 case GL_RG8I:
12757 return GL_BYTE;
12758 case GL_RG16UI:
12759 return GL_UNSIGNED_SHORT;
12760 case GL_RG16I:
12761 return GL_SHORT;
12762 case GL_RG32UI:
12763 return GL_UNSIGNED_INT;
12764 case GL_RG32I:
12765 return GL_INT;
12766 case GL_RGB8:
12767 case GL_SRGB8:
12768 return GL_UNSIGNED_BYTE;
12769 case GL_R11F_G11F_B10F:
12770 return GL_UNSIGNED_INT_10F_11F_11F_REV;
12771 case GL_RGB565:
12772 return GL_UNSIGNED_SHORT_5_6_5;
12773 case GL_RGB8_SNORM:
12774 return GL_BYTE;
12775 case GL_RGB9_E5:
12776 return GL_UNSIGNED_INT_5_9_9_9_REV;
12777 case GL_RGB16F:
12778 return GL_HALF_FLOAT;
12779 case GL_RGB32F:
12780 return GL_FLOAT;
12781 case GL_RGB8UI:
12782 return GL_UNSIGNED_BYTE;
12783 case GL_RGB8I:
12784 return GL_BYTE;
12785 case GL_RGB16UI:
12786 return GL_UNSIGNED_SHORT;
12787 case GL_RGB16I:
12788 return GL_SHORT;
12789 case GL_RGB32UI:
12790 return GL_UNSIGNED_INT;
12791 case GL_RGB32I:
12792 return GL_INT;
12793 case GL_RGBA8:
12794 return GL_UNSIGNED_BYTE;
12795 case GL_SRGB8_ALPHA8:
12796 return GL_UNSIGNED_BYTE;
12797 case GL_RGBA8_SNORM:
12798 return GL_BYTE;
12799 case GL_RGBA4:
12800 return GL_UNSIGNED_SHORT_4_4_4_4;
12801 case GL_RGB10_A2:
12802 return GL_UNSIGNED_INT_2_10_10_10_REV;
12803 case GL_RGB5_A1:
12804 return GL_UNSIGNED_SHORT_5_5_5_1;
12805 case GL_RGBA16F:
12806 return GL_HALF_FLOAT;
12807 case GL_RGBA32F:
12808 return GL_FLOAT;
12809 case GL_RGBA8UI:
12810 return GL_UNSIGNED_BYTE;
12811 case GL_RGBA8I:
12812 return GL_BYTE;
12813 case GL_RGB10_A2UI:
12814 return GL_UNSIGNED_INT_2_10_10_10_REV;
12815 case GL_RGBA16UI:
12816 return GL_UNSIGNED_SHORT;
12817 case GL_RGBA16I:
12818 return GL_SHORT;
12819 case GL_RGBA32I:
12820 return GL_INT;
12821 case GL_RGBA32UI:
12822 return GL_UNSIGNED_INT;
12823 case GL_DEPTH_COMPONENT16:
12824 return GL_UNSIGNED_SHORT;
12825 case GL_DEPTH_COMPONENT24:
12826 return GL_UNSIGNED_INT;
12827 case GL_DEPTH_COMPONENT32F:
12828 return GL_FLOAT;
12829 case GL_DEPTH24_STENCIL8:
12830 return GL_UNSIGNED_INT_24_8;
12831 case GL_DEPTH32F_STENCIL8:
12832 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
12833 case GL_LUMINANCE8_ALPHA8_EXT:
12834 return GL_UNSIGNED_BYTE;
12835 case GL_LUMINANCE8_EXT:
12836 return GL_UNSIGNED_BYTE;
12837 case GL_ALPHA8_EXT:
12838 return GL_UNSIGNED_BYTE;
12839 case GL_ALPHA32F_EXT:
12840 return GL_FLOAT;
12841 case GL_LUMINANCE32F_EXT:
12842 return GL_FLOAT;
12843 case GL_LUMINANCE_ALPHA32F_EXT:
12844 return GL_FLOAT;
12845 case GL_ALPHA16F_EXT:
12846 return GL_HALF_FLOAT_OES;
12847 case GL_LUMINANCE16F_EXT:
12848 return GL_HALF_FLOAT_OES;
12849 case GL_LUMINANCE_ALPHA16F_EXT:
12850 return GL_HALF_FLOAT_OES;
12851 case GL_BGRA8_EXT:
12852 return GL_UNSIGNED_BYTE;
12853 default:
12854 return GL_NONE;
12858 void GLES2DecoderImpl::DoTexStorage2DEXT(
12859 GLenum target,
12860 GLint levels,
12861 GLenum internal_format,
12862 GLsizei width,
12863 GLsizei height) {
12864 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12865 "width", width, "height", height);
12866 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
12867 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
12868 LOCAL_SET_GL_ERROR(
12869 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
12870 return;
12872 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12873 &state_, target);
12874 if (!texture_ref) {
12875 LOCAL_SET_GL_ERROR(
12876 GL_INVALID_OPERATION,
12877 "glTexStorage2DEXT", "unknown texture for target");
12878 return;
12880 Texture* texture = texture_ref->texture();
12881 if (texture->IsAttachedToFramebuffer()) {
12882 framebuffer_state_.clear_state_dirty = true;
12884 if (texture->IsImmutable()) {
12885 LOCAL_SET_GL_ERROR(
12886 GL_INVALID_OPERATION,
12887 "glTexStorage2DEXT", "texture is immutable");
12888 return;
12891 GLenum format = ExtractFormatFromStorageFormat(internal_format);
12892 GLenum type = ExtractTypeFromStorageFormat(internal_format);
12895 GLsizei level_width = width;
12896 GLsizei level_height = height;
12897 uint32 estimated_size = 0;
12898 for (int ii = 0; ii < levels; ++ii) {
12899 uint32 level_size = 0;
12900 if (!GLES2Util::ComputeImageDataSizes(
12901 level_width, level_height, 1, format, type, state_.unpack_alignment,
12902 &estimated_size, NULL, NULL) ||
12903 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
12904 LOCAL_SET_GL_ERROR(
12905 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
12906 return;
12908 level_width = std::max(1, level_width >> 1);
12909 level_height = std::max(1, level_height >> 1);
12911 if (!EnsureGPUMemoryAvailable(estimated_size)) {
12912 LOCAL_SET_GL_ERROR(
12913 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
12914 return;
12918 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12919 glTexStorage2DEXT(target, levels, internal_format, width, height);
12920 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12921 if (error == GL_NO_ERROR) {
12922 GLsizei level_width = width;
12923 GLsizei level_height = height;
12925 GLenum cur_format = feature_info_->IsES3Enabled() ?
12926 internal_format : format;
12927 for (int ii = 0; ii < levels; ++ii) {
12928 if (target == GL_TEXTURE_CUBE_MAP) {
12929 for (int jj = 0; jj < 6; ++jj) {
12930 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
12931 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
12932 level_width, level_height, 1, 0,
12933 format, type, gfx::Rect());
12935 } else {
12936 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
12937 level_width, level_height, 1, 0,
12938 format, type, gfx::Rect());
12940 level_width = std::max(1, level_width >> 1);
12941 level_height = std::max(1, level_height >> 1);
12943 texture->SetImmutable(true);
12947 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12948 uint32 immediate_data_size,
12949 const void* cmd_data) {
12950 return error::kUnknownCommand;
12953 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
12954 const GLbyte* data) {
12955 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12956 "context", logger_.GetLogPrefix(),
12957 "mailbox[0]", static_cast<unsigned char>(data[0]));
12959 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12960 &state_, target);
12961 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
12964 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
12965 GLenum target, const GLbyte* data) {
12966 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12967 "context", logger_.GetLogPrefix(),
12968 "mailbox[0]", static_cast<unsigned char>(data[0]));
12970 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
12971 target, data);
12974 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
12975 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
12976 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12977 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
12978 "mailbox that was not generated by "
12979 "GenMailboxCHROMIUM.";
12981 if (!texture_ref) {
12982 LOCAL_SET_GL_ERROR(
12983 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
12984 return;
12987 Texture* produced = texture_manager()->Produce(texture_ref);
12988 if (!produced) {
12989 LOCAL_SET_GL_ERROR(
12990 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
12991 return;
12994 if (produced->target() != target) {
12995 LOCAL_SET_GL_ERROR(
12996 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
12997 return;
13000 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13003 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13004 const GLbyte* data) {
13005 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13006 "context", logger_.GetLogPrefix(),
13007 "mailbox[0]", static_cast<unsigned char>(data[0]));
13008 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13009 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13010 "mailbox that was not generated by "
13011 "GenMailboxCHROMIUM.";
13013 scoped_refptr<TextureRef> texture_ref =
13014 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13015 if (!texture_ref.get()) {
13016 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13017 "glConsumeTextureCHROMIUM",
13018 "unknown texture for target");
13019 return;
13021 GLuint client_id = texture_ref->client_id();
13022 if (!client_id) {
13023 LOCAL_SET_GL_ERROR(
13024 GL_INVALID_OPERATION,
13025 "glConsumeTextureCHROMIUM", "unknown texture for target");
13026 return;
13028 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13029 if (!texture) {
13030 LOCAL_SET_GL_ERROR(
13031 GL_INVALID_OPERATION,
13032 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13033 return;
13035 if (texture->target() != target) {
13036 LOCAL_SET_GL_ERROR(
13037 GL_INVALID_OPERATION,
13038 "glConsumeTextureCHROMIUM", "invalid target");
13039 return;
13042 DeleteTexturesHelper(1, &client_id);
13043 texture_ref = texture_manager()->Consume(client_id, texture);
13044 glBindTexture(target, texture_ref->service_id());
13046 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13047 unit.bind_target = target;
13048 switch (target) {
13049 case GL_TEXTURE_2D:
13050 unit.bound_texture_2d = texture_ref;
13051 break;
13052 case GL_TEXTURE_CUBE_MAP:
13053 unit.bound_texture_cube_map = texture_ref;
13054 break;
13055 case GL_TEXTURE_EXTERNAL_OES:
13056 unit.bound_texture_external_oes = texture_ref;
13057 break;
13058 case GL_TEXTURE_RECTANGLE_ARB:
13059 unit.bound_texture_rectangle_arb = texture_ref;
13060 break;
13061 default:
13062 NOTREACHED(); // Validation should prevent us getting here.
13063 break;
13067 void GLES2DecoderImpl::EnsureTextureForClientId(
13068 GLenum target,
13069 GLuint client_id) {
13070 TextureRef* texture_ref = GetTexture(client_id);
13071 if (!texture_ref) {
13072 GLuint service_id;
13073 glGenTextures(1, &service_id);
13074 DCHECK_NE(0u, service_id);
13075 texture_ref = CreateTexture(client_id, service_id);
13076 texture_manager()->SetTarget(texture_ref, target);
13077 glBindTexture(target, service_id);
13078 RestoreCurrentTextureBindings(&state_, target);
13082 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13083 // provided is associated with a service_id/TextureRef for consistency, even if
13084 // the resulting texture is incomplete.
13085 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13086 uint32_t immediate_data_size,
13087 const void* cmd_data) {
13088 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13089 *static_cast<
13090 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13091 cmd_data);
13092 GLenum target = static_cast<GLenum>(c.target);
13093 uint32_t data_size;
13094 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13095 return error::kOutOfBounds;
13097 if (data_size > immediate_data_size) {
13098 return error::kOutOfBounds;
13100 const GLbyte* mailbox =
13101 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13102 if (!validators_->texture_bind_target.IsValid(target)) {
13103 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13104 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13105 return error::kNoError;
13107 if (mailbox == NULL) {
13108 return error::kOutOfBounds;
13110 uint32_t client_id = c.client_id;
13111 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13112 return error::kNoError;
13115 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13116 const GLbyte* data, GLuint client_id) {
13117 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13118 "context", logger_.GetLogPrefix(),
13119 "mailbox[0]", static_cast<unsigned char>(data[0]));
13120 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13121 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13122 "passed a mailbox that was not "
13123 "generated by GenMailboxCHROMIUM.";
13125 TextureRef* texture_ref = GetTexture(client_id);
13126 if (texture_ref) {
13127 // No need to call EnsureTextureForClientId here, the client_id already has
13128 // an associated texture.
13129 LOCAL_SET_GL_ERROR(
13130 GL_INVALID_OPERATION,
13131 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13132 return;
13134 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13135 if (!texture) {
13136 EnsureTextureForClientId(target, client_id);
13137 LOCAL_SET_GL_ERROR(
13138 GL_INVALID_OPERATION,
13139 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13140 return;
13143 if (texture->target() != target) {
13144 EnsureTextureForClientId(target, client_id);
13145 LOCAL_SET_GL_ERROR(
13146 GL_INVALID_OPERATION,
13147 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13148 return;
13151 texture_ref = texture_manager()->Consume(client_id, texture);
13154 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
13155 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
13156 return valuebuffer && valuebuffer->IsValid();
13159 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
13160 GLuint client_id) {
13161 Valuebuffer* valuebuffer = NULL;
13162 if (client_id != 0) {
13163 valuebuffer = GetValuebuffer(client_id);
13164 if (!valuebuffer) {
13165 if (!group_->bind_generates_resource()) {
13166 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
13167 "id not generated by glBindValuebufferCHROMIUM");
13168 return;
13171 // It's a new id so make a valuebuffer for it.
13172 CreateValuebuffer(client_id);
13173 valuebuffer = GetValuebuffer(client_id);
13175 valuebuffer->MarkAsValid();
13177 state_.bound_valuebuffer = valuebuffer;
13180 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
13181 GLenum subscription) {
13182 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13183 return;
13185 state_.bound_valuebuffer.get()->AddSubscription(subscription);
13188 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
13189 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13190 return;
13192 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
13195 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
13196 GLenum target,
13197 GLenum subscription) {
13198 if (!CheckCurrentValuebufferForSubscription(
13199 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
13200 return;
13202 if (!CheckSubscriptionTarget(location, subscription,
13203 "glPopulateSubscribedValuesCHROMIUM")) {
13204 return;
13206 const ValueState* state =
13207 state_.bound_valuebuffer.get()->GetState(subscription);
13208 if (state) {
13209 switch (subscription) {
13210 case GL_MOUSE_POSITION_CHROMIUM:
13211 DoUniform2iv(location, 1, state->int_value);
13212 break;
13213 default:
13214 NOTREACHED() << "Unhandled uniform subscription target "
13215 << subscription;
13216 break;
13221 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13222 GLsizei length, const GLchar* marker) {
13223 if (!marker) {
13224 marker = "";
13226 debug_marker_manager_.SetMarker(
13227 length ? std::string(marker, length) : std::string(marker));
13230 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13231 GLsizei /*length*/, const GLchar* /*marker*/) {
13234 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13237 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13238 GLenum target, GLint image_id) {
13239 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13241 if (target == GL_TEXTURE_CUBE_MAP) {
13242 LOCAL_SET_GL_ERROR(
13243 GL_INVALID_ENUM,
13244 "glBindTexImage2DCHROMIUM", "invalid target");
13245 return;
13248 // Default target might be conceptually valid, but disallow it to avoid
13249 // accidents.
13250 TextureRef* texture_ref =
13251 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13252 if (!texture_ref) {
13253 LOCAL_SET_GL_ERROR(
13254 GL_INVALID_OPERATION,
13255 "glBindTexImage2DCHROMIUM", "no texture bound");
13256 return;
13259 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13260 if (!gl_image) {
13261 LOCAL_SET_GL_ERROR(
13262 GL_INVALID_OPERATION,
13263 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13264 return;
13268 ScopedGLErrorSuppressor suppressor(
13269 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13270 if (!gl_image->BindTexImage(target)) {
13271 LOCAL_SET_GL_ERROR(
13272 GL_INVALID_OPERATION,
13273 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13274 return;
13278 gfx::Size size = gl_image->GetSize();
13279 texture_manager()->SetLevelInfo(
13280 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
13281 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
13282 gfx::Rect(size));
13283 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
13286 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13287 GLenum target, GLint image_id) {
13288 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13290 // Default target might be conceptually valid, but disallow it to avoid
13291 // accidents.
13292 TextureRef* texture_ref =
13293 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13294 if (!texture_ref) {
13295 LOCAL_SET_GL_ERROR(
13296 GL_INVALID_OPERATION,
13297 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13298 return;
13301 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13302 if (!gl_image) {
13303 LOCAL_SET_GL_ERROR(
13304 GL_INVALID_OPERATION,
13305 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13306 return;
13309 // Do nothing when image is not currently bound.
13310 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
13311 return;
13314 ScopedGLErrorSuppressor suppressor(
13315 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13316 gl_image->ReleaseTexImage(target);
13319 texture_manager()->SetLevelInfo(
13320 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
13321 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
13324 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13325 uint32 immediate_data_size,
13326 const void* cmd_data) {
13327 const gles2::cmds::TraceBeginCHROMIUM& c =
13328 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
13329 Bucket* category_bucket = GetBucket(c.category_bucket_id);
13330 Bucket* name_bucket = GetBucket(c.name_bucket_id);
13331 if (!category_bucket || category_bucket->size() == 0 ||
13332 !name_bucket || name_bucket->size() == 0) {
13333 return error::kInvalidArguments;
13336 std::string category_name;
13337 std::string trace_name;
13338 if (!category_bucket->GetAsString(&category_name) ||
13339 !name_bucket->GetAsString(&trace_name)) {
13340 return error::kInvalidArguments;
13343 debug_marker_manager_.PushGroup(trace_name);
13344 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
13345 LOCAL_SET_GL_ERROR(
13346 GL_INVALID_OPERATION,
13347 "glTraceBeginCHROMIUM", "unable to create begin trace");
13348 return error::kNoError;
13350 return error::kNoError;
13353 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13354 debug_marker_manager_.PopGroup();
13355 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
13356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13357 "glTraceEndCHROMIUM", "no trace begin found");
13358 return;
13362 void GLES2DecoderImpl::DoDrawBuffersEXT(
13363 GLsizei count, const GLenum* bufs) {
13364 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
13365 LOCAL_SET_GL_ERROR(
13366 GL_INVALID_VALUE,
13367 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13368 return;
13371 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
13372 if (framebuffer) {
13373 for (GLsizei i = 0; i < count; ++i) {
13374 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
13375 bufs[i] != GL_NONE) {
13376 LOCAL_SET_GL_ERROR(
13377 GL_INVALID_OPERATION,
13378 "glDrawBuffersEXT",
13379 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13380 return;
13383 glDrawBuffersARB(count, bufs);
13384 framebuffer->SetDrawBuffers(count, bufs);
13385 } else { // backbuffer
13386 if (count > 1 ||
13387 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
13388 LOCAL_SET_GL_ERROR(
13389 GL_INVALID_OPERATION,
13390 "glDrawBuffersEXT",
13391 "more than one buffer or bufs not GL_NONE or GL_BACK");
13392 return;
13394 GLenum mapped_buf = bufs[0];
13395 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13396 bufs[0] == GL_BACK) {
13397 mapped_buf = GL_COLOR_ATTACHMENT0;
13399 glDrawBuffersARB(count, &mapped_buf);
13400 group_->set_draw_buffer(bufs[0]);
13404 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
13405 MarkContextLost(GetContextLostReasonFromResetStatus(current));
13406 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
13407 reset_by_robustness_extension_ = true;
13410 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13411 // On Adreno Android devices we need to use a workaround to force caches to
13412 // clear.
13413 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
13414 context_->ReleaseCurrent(nullptr);
13415 context_->MakeCurrent(surface_.get());
13419 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
13420 const GLfloat* matrix) {
13421 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13422 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13423 if (!features().chromium_path_rendering) {
13424 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13425 "glMatrixLoadfCHROMIUM",
13426 "function not available");
13427 return;
13430 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13431 ? state_.projection_matrix
13432 : state_.modelview_matrix;
13433 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
13434 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13435 // since the values of the _NV and _CHROMIUM tokens match.
13436 glMatrixLoadfEXT(matrix_mode, matrix);
13439 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
13440 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13441 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13443 if (!features().chromium_path_rendering) {
13444 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13445 "glMatrixLoadIdentityCHROMIUM",
13446 "function not available");
13447 return;
13450 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13451 ? state_.projection_matrix
13452 : state_.modelview_matrix;
13453 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
13454 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13455 // since the values of the _NV and _CHROMIUM tokens match.
13456 glMatrixLoadIdentityEXT(matrix_mode);
13459 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13460 const char* function_name,
13461 TextureRef* texture_ref,
13462 GLenum target,
13463 GLint level,
13464 const void * data) {
13465 // We only support async uploads to 2D textures for now.
13466 if (GL_TEXTURE_2D != target) {
13467 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
13468 return false;
13470 // We only support uploads to level zero for now.
13471 if (level != 0) {
13472 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
13473 return false;
13475 // A transfer buffer must be bound, even for asyncTexImage2D.
13476 if (data == NULL) {
13477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
13478 return false;
13480 // We only support one async transfer in progress.
13481 if (!texture_ref ||
13482 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
13483 LOCAL_SET_GL_ERROR(
13484 GL_INVALID_OPERATION,
13485 function_name, "transfer already in progress");
13486 return false;
13488 return true;
13491 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13492 uint32 async_upload_token,
13493 uint32 sync_data_shm_id,
13494 uint32 sync_data_shm_offset) {
13495 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
13496 if (!buffer.get() ||
13497 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
13498 return base::Closure();
13500 AsyncMemoryParams mem_params(buffer,
13501 sync_data_shm_offset,
13502 sizeof(AsyncUploadSync));
13504 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
13505 new AsyncUploadTokenCompletionObserver(async_upload_token));
13507 return base::Bind(
13508 &AsyncPixelTransferManager::AsyncNotifyCompletion,
13509 base::Unretained(GetAsyncPixelTransferManager()),
13510 mem_params,
13511 observer);
13514 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13515 uint32 immediate_data_size,
13516 const void* cmd_data) {
13517 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
13518 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
13519 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13520 GLenum target = static_cast<GLenum>(c.target);
13521 GLint level = static_cast<GLint>(c.level);
13522 GLenum internal_format = static_cast<GLenum>(c.internalformat);
13523 GLsizei width = static_cast<GLsizei>(c.width);
13524 GLsizei height = static_cast<GLsizei>(c.height);
13525 GLint border = static_cast<GLint>(c.border);
13526 GLenum format = static_cast<GLenum>(c.format);
13527 GLenum type = static_cast<GLenum>(c.type);
13528 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
13529 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
13530 uint32 pixels_size;
13531 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13532 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13533 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13535 base::ScopedClosureRunner scoped_completion_callback;
13536 if (async_upload_token) {
13537 base::Closure completion_closure =
13538 AsyncUploadTokenCompletionClosure(async_upload_token,
13539 sync_data_shm_id,
13540 sync_data_shm_offset);
13541 if (completion_closure.is_null())
13542 return error::kInvalidArguments;
13544 scoped_completion_callback.Reset(completion_closure);
13547 // TODO(epenner): Move this and copies of this memory validation
13548 // into ValidateTexImage2D step.
13549 if (!GLES2Util::ComputeImageDataSizes(
13550 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
13551 NULL, NULL)) {
13552 return error::kOutOfBounds;
13554 const void* pixels = NULL;
13555 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
13556 pixels = GetSharedMemoryAs<const void*>(
13557 pixels_shm_id, pixels_shm_offset, pixels_size);
13558 if (!pixels) {
13559 return error::kOutOfBounds;
13563 TextureManager::DoTexImageArguments args = {
13564 target, level, internal_format, width, height, 1, border, format, type,
13565 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
13566 TextureRef* texture_ref;
13567 // All the normal glTexSubImage2D validation.
13568 if (!texture_manager()->ValidateTexImage(
13569 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
13570 return error::kNoError;
13573 // Extra async validation.
13574 Texture* texture = texture_ref->texture();
13575 if (!ValidateAsyncTransfer(
13576 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
13577 return error::kNoError;
13579 // Don't allow async redefinition of a textures.
13580 if (texture->IsDefined()) {
13581 LOCAL_SET_GL_ERROR(
13582 GL_INVALID_OPERATION,
13583 "glAsyncTexImage2DCHROMIUM", "already defined");
13584 return error::kNoError;
13587 if (!EnsureGPUMemoryAvailable(pixels_size)) {
13588 LOCAL_SET_GL_ERROR(
13589 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
13590 return error::kNoError;
13593 // Setup the parameters.
13594 AsyncTexImage2DParams tex_params = {
13595 target, level, static_cast<GLenum>(internal_format),
13596 width, height, border, format, type};
13597 AsyncMemoryParams mem_params(
13598 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
13600 // Set up the async state if needed, and make the texture
13601 // immutable so the async state stays valid. The level info
13602 // is set up lazily when the transfer completes.
13603 AsyncPixelTransferDelegate* delegate =
13604 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
13605 tex_params);
13606 texture->SetImmutable(true);
13608 delegate->AsyncTexImage2D(
13609 tex_params,
13610 mem_params,
13611 base::Bind(&TextureManager::SetLevelInfoFromParams,
13612 // The callback is only invoked if the transfer delegate still
13613 // exists, which implies through manager->texture_ref->state
13614 // ownership that both of these pointers are valid.
13615 base::Unretained(texture_manager()),
13616 base::Unretained(texture_ref),
13617 tex_params));
13618 return error::kNoError;
13621 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13622 uint32 immediate_data_size,
13623 const void* cmd_data) {
13624 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
13625 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
13626 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13627 GLenum target = static_cast<GLenum>(c.target);
13628 GLint level = static_cast<GLint>(c.level);
13629 GLint xoffset = static_cast<GLint>(c.xoffset);
13630 GLint yoffset = static_cast<GLint>(c.yoffset);
13631 GLsizei width = static_cast<GLsizei>(c.width);
13632 GLsizei height = static_cast<GLsizei>(c.height);
13633 GLenum format = static_cast<GLenum>(c.format);
13634 GLenum type = static_cast<GLenum>(c.type);
13635 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13636 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13637 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13639 base::ScopedClosureRunner scoped_completion_callback;
13640 if (async_upload_token) {
13641 base::Closure completion_closure =
13642 AsyncUploadTokenCompletionClosure(async_upload_token,
13643 sync_data_shm_id,
13644 sync_data_shm_offset);
13645 if (completion_closure.is_null())
13646 return error::kInvalidArguments;
13648 scoped_completion_callback.Reset(completion_closure);
13651 // TODO(epenner): Move this and copies of this memory validation
13652 // into ValidateTexSubImage2D step.
13653 uint32 data_size;
13654 if (!GLES2Util::ComputeImageDataSizes(
13655 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13656 NULL, NULL)) {
13657 return error::kOutOfBounds;
13659 const void* pixels = GetSharedMemoryAs<const void*>(
13660 c.data_shm_id, c.data_shm_offset, data_size);
13662 // All the normal glTexSubImage2D validation.
13663 error::Error error = error::kNoError;
13664 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13665 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13666 return error;
13669 // Extra async validation.
13670 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13671 &state_, target);
13672 Texture* texture = texture_ref->texture();
13673 if (!ValidateAsyncTransfer(
13674 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13675 return error::kNoError;
13677 // Guarantee async textures are always 'cleared' as follows:
13678 // - AsyncTexImage2D can not redefine an existing texture
13679 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13680 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13681 // - Textures become immutable after an async call.
13682 // This way we know in all cases that an async texture is always clear.
13683 if (!texture->SafeToRenderFrom()) {
13684 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13685 target, level)) {
13686 LOCAL_SET_GL_ERROR(
13687 GL_OUT_OF_MEMORY,
13688 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13689 return error::kNoError;
13693 // Setup the parameters.
13694 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
13695 width, height, format, type};
13696 AsyncMemoryParams mem_params(
13697 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
13698 AsyncPixelTransferDelegate* delegate =
13699 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13700 if (!delegate) {
13701 // TODO(epenner): We may want to enforce exclusive use
13702 // of async APIs in which case this should become an error,
13703 // (the texture should have been async defined).
13704 AsyncTexImage2DParams define_params = {target, level,
13705 0, 0, 0, 0, 0, 0};
13706 texture->GetLevelSize(
13707 target, level, &define_params.width, &define_params.height, nullptr);
13708 texture->GetLevelType(
13709 target, level, &define_params.type, &define_params.internal_format);
13710 // Set up the async state if needed, and make the texture
13711 // immutable so the async state stays valid.
13712 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
13713 texture_ref, define_params);
13714 texture->SetImmutable(true);
13717 delegate->AsyncTexSubImage2D(tex_params, mem_params);
13718 return error::kNoError;
13721 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13722 uint32 immediate_data_size,
13723 const void* cmd_data) {
13724 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
13725 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
13726 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13727 GLenum target = static_cast<GLenum>(c.target);
13729 if (GL_TEXTURE_2D != target) {
13730 LOCAL_SET_GL_ERROR(
13731 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
13732 return error::kNoError;
13734 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13735 &state_, target);
13736 if (!texture_ref) {
13737 LOCAL_SET_GL_ERROR(
13738 GL_INVALID_OPERATION,
13739 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13740 return error::kNoError;
13742 AsyncPixelTransferDelegate* delegate =
13743 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13744 if (!delegate) {
13745 LOCAL_SET_GL_ERROR(
13746 GL_INVALID_OPERATION,
13747 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13748 return error::kNoError;
13750 delegate->WaitForTransferCompletion();
13751 ProcessFinishedAsyncTransfers();
13752 return error::kNoError;
13755 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13756 uint32 immediate_data_size,
13757 const void* data) {
13758 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13760 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13761 ProcessFinishedAsyncTransfers();
13762 return error::kNoError;
13765 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
13766 uint32_t immediate_data_size, const void* cmd_data) {
13767 if (!unsafe_es3_apis_enabled())
13768 return error::kUnknownCommand;
13769 const gles2::cmds::UniformBlockBinding& c =
13770 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
13771 GLuint client_id = c.program;
13772 GLuint index = static_cast<GLuint>(c.index);
13773 GLuint binding = static_cast<GLuint>(c.binding);
13774 Program* program = GetProgramInfoNotShader(
13775 client_id, "glUniformBlockBinding");
13776 if (!program) {
13777 return error::kNoError;
13779 GLuint service_id = program->service_id();
13780 glUniformBlockBinding(service_id, index, binding);
13781 return error::kNoError;
13784 error::Error GLES2DecoderImpl::HandleClientWaitSync(
13785 uint32_t immediate_data_size, const void* cmd_data) {
13786 if (!unsafe_es3_apis_enabled())
13787 return error::kUnknownCommand;
13788 const gles2::cmds::ClientWaitSync& c =
13789 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
13790 GLuint sync = static_cast<GLuint>(c.sync);
13791 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13792 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13793 typedef cmds::ClientWaitSync::Result Result;
13794 Result* result_dst = GetSharedMemoryAs<Result*>(
13795 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
13796 if (!result_dst) {
13797 return error::kOutOfBounds;
13799 if (*result_dst != GL_WAIT_FAILED) {
13800 return error::kInvalidArguments;
13802 GLsync service_sync = 0;
13803 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13804 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
13805 return error::kNoError;
13807 *result_dst = glClientWaitSync(service_sync, flags, timeout);
13808 return error::kNoError;
13811 error::Error GLES2DecoderImpl::HandleWaitSync(
13812 uint32_t immediate_data_size, const void* cmd_data) {
13813 if (!unsafe_es3_apis_enabled())
13814 return error::kUnknownCommand;
13815 const gles2::cmds::WaitSync& c =
13816 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
13817 GLuint sync = static_cast<GLuint>(c.sync);
13818 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13819 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13820 GLsync service_sync = 0;
13821 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13822 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
13823 return error::kNoError;
13825 glWaitSync(service_sync, flags, timeout);
13826 return error::kNoError;
13829 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
13830 uint32_t immediate_data_size, const void* cmd_data) {
13831 if (!unsafe_es3_apis_enabled())
13832 return error::kUnknownCommand;
13833 const gles2::cmds::GetInternalformativ& c =
13834 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
13835 GLenum target = static_cast<GLenum>(c.target);
13836 GLenum format = static_cast<GLenum>(c.format);
13837 GLenum pname = static_cast<GLenum>(c.pname);
13838 if (!validators_->render_buffer_target.IsValid(target)) {
13839 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
13840 return error::kNoError;
13842 if (!validators_->render_buffer_format.IsValid(format)) {
13843 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
13844 return error::kNoError;
13846 if (!validators_->internal_format_parameter.IsValid(pname)) {
13847 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
13848 return error::kNoError;
13850 typedef cmds::GetInternalformativ::Result Result;
13851 GLsizei num_values = 0;
13852 switch (pname) {
13853 case GL_NUM_SAMPLE_COUNTS:
13854 num_values = 1;
13855 break;
13856 case GL_SAMPLES:
13858 GLint value = 0;
13859 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
13860 num_values = static_cast<GLsizei>(value);
13862 break;
13863 default:
13864 NOTREACHED();
13865 break;
13867 Result* result = GetSharedMemoryAs<Result*>(
13868 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
13869 GLint* params = result ? result->GetData() : NULL;
13870 if (params == NULL) {
13871 return error::kOutOfBounds;
13873 // Check that the client initialized the result.
13874 if (result->size != 0) {
13875 return error::kInvalidArguments;
13877 glGetInternalformativ(target, format, pname, num_values, params);
13878 result->SetNumResults(num_values);
13879 return error::kNoError;
13882 error::Error GLES2DecoderImpl::HandleMapBufferRange(
13883 uint32_t immediate_data_size, const void* cmd_data) {
13884 if (!unsafe_es3_apis_enabled()) {
13885 return error::kUnknownCommand;
13887 const gles2::cmds::MapBufferRange& c =
13888 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
13889 GLenum target = static_cast<GLenum>(c.target);
13890 GLbitfield access = static_cast<GLbitfield>(c.access);
13891 GLintptr offset = static_cast<GLintptr>(c.offset);
13892 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
13894 typedef cmds::MapBufferRange::Result Result;
13895 Result* result = GetSharedMemoryAs<Result*>(
13896 c.result_shm_id, c.result_shm_offset, sizeof(*result));
13897 if (!result) {
13898 return error::kOutOfBounds;
13900 if (*result != 0) {
13901 *result = 0;
13902 return error::kInvalidArguments;
13904 int8_t* mem =
13905 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
13906 if (!mem) {
13907 return error::kOutOfBounds;
13910 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
13911 if ((access & mask) == mask) {
13912 // TODO(zmo): To be on the safe side, always map
13913 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13914 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
13915 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
13917 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13918 // undefined behaviors.
13919 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
13920 if ((access & mask) == mask) {
13921 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
13922 "incompatible access bits");
13923 return error::kNoError;
13925 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
13926 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
13927 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13928 access = (access | GL_MAP_READ_BIT);
13930 void* ptr = glMapBufferRange(target, offset, size, access);
13931 if (ptr == nullptr) {
13932 return error::kNoError;
13934 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13935 DCHECK(buffer);
13936 buffer->SetMappedRange(offset, size, access, ptr,
13937 GetSharedMemoryBuffer(c.data_shm_id));
13938 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13939 memcpy(mem, ptr, size);
13941 *result = 1;
13942 return error::kNoError;
13945 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
13946 uint32_t immediate_data_size, const void* cmd_data) {
13947 if (!unsafe_es3_apis_enabled()) {
13948 return error::kUnknownCommand;
13950 const gles2::cmds::UnmapBuffer& c =
13951 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
13952 GLenum target = static_cast<GLenum>(c.target);
13954 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13955 if (!buffer) {
13956 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
13957 return error::kNoError;
13959 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
13960 if (!mapped_range) {
13961 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
13962 "buffer is unmapped");
13963 return error::kNoError;
13965 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
13966 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
13967 GL_MAP_FLUSH_EXPLICIT_BIT) {
13968 // If we don't need to write back, or explict flush is required, no copying
13969 // back is needed.
13970 } else {
13971 void* mem = mapped_range->GetShmPointer();
13972 if (!mem) {
13973 return error::kOutOfBounds;
13975 DCHECK(mapped_range->pointer);
13976 memcpy(mapped_range->pointer, mem, mapped_range->size);
13978 buffer->RemoveMappedRange();
13979 GLboolean rt = glUnmapBuffer(target);
13980 if (rt == GL_FALSE) {
13981 // At this point, we have already done the necessary validation, so
13982 // GL_FALSE indicates data corruption.
13983 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13984 // the second unmap could still return GL_FALSE. For now, we simply lose
13985 // the contexts in the share group.
13986 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13987 // Need to lose current context before broadcasting!
13988 MarkContextLost(error::kGuilty);
13989 group_->LoseContexts(error::kInnocent);
13990 return error::kLostContext;
13992 return error::kNoError;
13995 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13996 TextureRef* texture_ref) {
13997 Texture* texture = texture_ref->texture();
13998 DoDidUseTexImageIfNeeded(texture, texture->target());
14001 // Note that GL_LOST_CONTEXT is specific to GLES.
14002 // For desktop GL we have to query the reset status proactively.
14003 void GLES2DecoderImpl::OnContextLostError() {
14004 if (!WasContextLost()) {
14005 // Need to lose current context before broadcasting!
14006 CheckResetStatus();
14007 group_->LoseContexts(error::kUnknown);
14008 reset_by_robustness_extension_ = true;
14012 void GLES2DecoderImpl::OnOutOfMemoryError() {
14013 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14014 error::ContextLostReason other = error::kOutOfMemory;
14015 if (CheckResetStatus()) {
14016 other = error::kUnknown;
14017 } else {
14018 // Need to lose current context before broadcasting!
14019 MarkContextLost(error::kOutOfMemory);
14021 group_->LoseContexts(other);
14025 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14026 uint32 immediate_data_size,
14027 const void* cmd_data) {
14028 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14029 const gles2::cmds::GenPathsCHROMIUM& c =
14030 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14031 if (!features().chromium_path_rendering) {
14032 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14033 "function not available");
14034 return error::kNoError;
14037 GLsizei range = static_cast<GLsizei>(c.range);
14038 if (range < 0) {
14039 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14040 return error::kNoError;
14043 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14044 if (first_client_id == 0)
14045 return error::kInvalidArguments;
14047 if (range == 0)
14048 return error::kNoError;
14050 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14051 return error::kInvalidArguments;
14053 return error::kNoError;
14055 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14056 uint32_t immediate_data_size,
14057 const void* cmd_data) {
14058 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14059 const gles2::cmds::DeletePathsCHROMIUM& c =
14060 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14061 if (!features().chromium_path_rendering) {
14062 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14063 "function not available");
14064 return error::kNoError;
14067 GLsizei range = static_cast<GLsizei>(c.range);
14068 if (range < 0) {
14069 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14070 return error::kNoError;
14073 if (range == 0)
14074 return error::kNoError;
14076 GLuint first_client_id = c.first_client_id;
14077 // first_client_id can be 0, because non-existing path ids are skipped.
14079 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14080 return error::kInvalidArguments;
14082 return error::kNoError;
14085 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14086 uint32 immediate_data_size,
14087 const void* cmd_data) {
14088 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14089 const gles2::cmds::PathCommandsCHROMIUM& c =
14090 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14091 if (!features().chromium_path_rendering) {
14092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14093 "function not available");
14094 return error::kNoError;
14097 GLuint service_id = 0;
14098 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14099 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14100 "invalid path name");
14101 return error::kNoError;
14104 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14105 if (num_commands < 0) {
14106 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14107 return error::kNoError;
14110 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14111 if (num_coords < 0) {
14112 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14113 return error::kNoError;
14116 GLenum coord_type = static_cast<uint32>(c.coordType);
14117 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14118 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14119 return error::kNoError;
14122 const GLubyte* commands = NULL;
14123 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14125 if (num_commands > 0) {
14126 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14127 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14128 if (commands_shm_id != 0 || commands_shm_offset != 0)
14129 commands = GetSharedMemoryAs<const GLubyte*>(
14130 commands_shm_id, commands_shm_offset, num_commands);
14132 if (!commands)
14133 return error::kOutOfBounds;
14135 for (GLsizei i = 0; i < num_commands; ++i) {
14136 switch (commands[i]) {
14137 case GL_CLOSE_PATH_CHROMIUM:
14138 // Close has no coords.
14139 break;
14140 case GL_MOVE_TO_CHROMIUM:
14141 // Fallthrough.
14142 case GL_LINE_TO_CHROMIUM:
14143 num_coords_expected += 2;
14144 break;
14145 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14146 num_coords_expected += 4;
14147 break;
14148 case GL_CUBIC_CURVE_TO_CHROMIUM:
14149 num_coords_expected += 6;
14150 break;
14151 case GL_CONIC_CURVE_TO_CHROMIUM:
14152 num_coords_expected += 5;
14153 break;
14154 default:
14155 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14156 return error::kNoError;
14161 if (!num_coords_expected.IsValid() ||
14162 num_coords != num_coords_expected.ValueOrDie()) {
14163 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14164 "numCoords does not match commands");
14165 return error::kNoError;
14168 const void* coords = NULL;
14170 if (num_coords > 0) {
14171 uint32 coords_size = 0;
14172 uint32 coord_type_size =
14173 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14174 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14175 return error::kOutOfBounds;
14177 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14178 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14179 if (coords_shm_id != 0 || coords_shm_offset != 0)
14180 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14181 coords_size);
14183 if (!coords)
14184 return error::kOutOfBounds;
14187 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14188 coords);
14190 return error::kNoError;
14193 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14194 uint32 immediate_data_size,
14195 const void* cmd_data) {
14196 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14197 const gles2::cmds::PathParameterfCHROMIUM& c =
14198 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14199 if (!features().chromium_path_rendering) {
14200 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14201 "function not available");
14202 return error::kNoError;
14204 GLuint service_id = 0;
14205 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14206 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14207 "invalid path name");
14208 return error::kNoError;
14211 GLenum pname = static_cast<GLenum>(c.pname);
14212 GLfloat value = static_cast<GLfloat>(c.value);
14213 bool hasValueError = false;
14215 switch (pname) {
14216 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14217 case GL_PATH_MITER_LIMIT_CHROMIUM:
14218 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14219 break;
14220 case GL_PATH_STROKE_BOUND_CHROMIUM:
14221 value = std::max(std::min(1.0f, value), 0.0f);
14222 break;
14223 case GL_PATH_END_CAPS_CHROMIUM:
14224 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14225 static_cast<GLint>(value));
14226 break;
14227 case GL_PATH_JOIN_STYLE_CHROMIUM:
14228 hasValueError = !validators_->path_parameter_join_values.IsValid(
14229 static_cast<GLint>(value));
14230 break;
14231 default:
14232 DCHECK(!validators_->path_parameter.IsValid(pname));
14233 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14234 return error::kNoError;
14236 DCHECK(validators_->path_parameter.IsValid(pname));
14238 if (hasValueError) {
14239 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14240 return error::kNoError;
14243 glPathParameterfNV(service_id, pname, value);
14244 return error::kNoError;
14247 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14248 uint32 immediate_data_size,
14249 const void* cmd_data) {
14250 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14251 const gles2::cmds::PathParameteriCHROMIUM& c =
14252 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14253 if (!features().chromium_path_rendering) {
14254 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14255 "function not available");
14256 return error::kNoError;
14258 GLuint service_id = 0;
14259 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14260 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14261 "invalid path name");
14262 return error::kNoError;
14265 GLenum pname = static_cast<GLenum>(c.pname);
14266 GLint value = static_cast<GLint>(c.value);
14267 bool hasValueError = false;
14269 switch (pname) {
14270 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14271 case GL_PATH_MITER_LIMIT_CHROMIUM:
14272 hasValueError = value < 0;
14273 break;
14274 case GL_PATH_STROKE_BOUND_CHROMIUM:
14275 value = std::max(std::min(1, value), 0);
14276 break;
14277 case GL_PATH_END_CAPS_CHROMIUM:
14278 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14279 break;
14280 case GL_PATH_JOIN_STYLE_CHROMIUM:
14281 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14282 break;
14283 default:
14284 DCHECK(!validators_->path_parameter.IsValid(pname));
14285 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14286 return error::kNoError;
14288 DCHECK(validators_->path_parameter.IsValid(pname));
14290 if (hasValueError) {
14291 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14292 return error::kNoError;
14295 glPathParameteriNV(service_id, pname, value);
14296 return error::kNoError;
14299 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14300 uint32 immediate_data_size,
14301 const void* cmd_data) {
14302 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14303 const gles2::cmds::StencilFillPathCHROMIUM& c =
14304 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14305 if (!features().chromium_path_rendering) {
14306 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14307 "function not available");
14308 return error::kNoError;
14310 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14311 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14312 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14313 return error::kNoError;
14315 GLuint mask = static_cast<GLuint>(c.mask);
14316 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14317 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14318 GLES2Util::IsNPOT(mask + 1)) {
14319 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14320 "mask + 1 is not power of two");
14321 return error::kNoError;
14323 GLuint service_id = 0;
14324 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14325 // "If /path/ does not name an existing path object, the command does
14326 // nothing (and no error is generated)."
14327 // This holds for other rendering functions, too.
14328 return error::kNoError;
14330 ApplyDirtyState();
14331 glStencilFillPathNV(service_id, fill_mode, mask);
14332 return error::kNoError;
14335 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14336 uint32 immediate_data_size,
14337 const void* cmd_data) {
14338 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14339 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14340 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14341 if (!features().chromium_path_rendering) {
14342 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14343 "function not available");
14344 return error::kNoError;
14346 GLuint service_id = 0;
14347 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14348 return error::kNoError;
14350 GLint reference = static_cast<GLint>(c.reference);
14351 GLuint mask = static_cast<GLuint>(c.mask);
14352 ApplyDirtyState();
14353 glStencilStrokePathNV(service_id, reference, mask);
14354 return error::kNoError;
14357 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14358 uint32 immediate_data_size,
14359 const void* cmd_data) {
14360 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14361 const gles2::cmds::CoverFillPathCHROMIUM& c =
14362 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14363 if (!features().chromium_path_rendering) {
14364 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14365 "function not available");
14366 return error::kNoError;
14368 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14369 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14370 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14371 return error::kNoError;
14373 GLuint service_id = 0;
14374 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14375 return error::kNoError;
14377 ApplyDirtyState();
14378 glCoverFillPathNV(service_id, cover_mode);
14379 return error::kNoError;
14382 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14383 uint32 immediate_data_size,
14384 const void* cmd_data) {
14385 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14386 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14387 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14388 if (!features().chromium_path_rendering) {
14389 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14390 "function not available");
14391 return error::kNoError;
14393 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14394 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14395 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14396 return error::kNoError;
14398 GLuint service_id = 0;
14399 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14400 return error::kNoError;
14402 ApplyDirtyState();
14403 glCoverStrokePathNV(service_id, cover_mode);
14404 return error::kNoError;
14407 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14408 uint32 immediate_data_size,
14409 const void* cmd_data) {
14410 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14411 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14412 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14413 cmd_data);
14414 if (!features().chromium_path_rendering) {
14415 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14416 "function not available");
14417 return error::kNoError;
14419 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14420 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14421 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14422 return error::kNoError;
14424 GLuint mask = static_cast<GLuint>(c.mask);
14425 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14426 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14427 GLES2Util::IsNPOT(mask + 1)) {
14428 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14429 "mask + 1 is not power of two");
14430 return error::kNoError;
14432 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14433 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14434 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14435 return error::kNoError;
14437 GLuint service_id = 0;
14438 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14439 return error::kNoError;
14441 ApplyDirtyState();
14442 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
14443 return error::kNoError;
14446 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14447 uint32 immediate_data_size,
14448 const void* cmd_data) {
14449 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
14450 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
14451 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
14452 cmd_data);
14453 if (!features().chromium_path_rendering) {
14454 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14455 "function not available");
14456 return error::kNoError;
14458 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14459 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14460 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14461 return error::kNoError;
14463 GLuint service_id = 0;
14464 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14465 return error::kNoError;
14467 GLint reference = static_cast<GLint>(c.reference);
14468 GLuint mask = static_cast<GLuint>(c.mask);
14469 ApplyDirtyState();
14470 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
14471 return error::kNoError;
14474 // Include the auto-generated part of this file. We split this because it means
14475 // we can easily edit the non-auto generated parts right here in this file
14476 // instead of having to edit some template or the code generator.
14477 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14479 } // namespace gles2
14480 } // namespace gpu