Implemented GPU Timer Disjoint Value checking on the GLES2 Client.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob1f72f242dea65274d81538d43f4c6327056abaa1
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
15 #include "base/callback.h"
16 #include "base/callback_helpers.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/trace_event/trace_event.h"
25 #include "base/trace_event/trace_event_synthetic_delay.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/mailbox.h"
32 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
34 #include "gpu/command_buffer/service/buffer_manager.h"
35 #include "gpu/command_buffer/service/context_group.h"
36 #include "gpu/command_buffer/service/context_state.h"
37 #include "gpu/command_buffer/service/error_state.h"
38 #include "gpu/command_buffer/service/feature_info.h"
39 #include "gpu/command_buffer/service/framebuffer_manager.h"
40 #include "gpu/command_buffer/service/gl_utils.h"
41 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
42 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
43 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
44 #include "gpu/command_buffer/service/gpu_state_tracer.h"
45 #include "gpu/command_buffer/service/gpu_switches.h"
46 #include "gpu/command_buffer/service/gpu_tracer.h"
47 #include "gpu/command_buffer/service/image_manager.h"
48 #include "gpu/command_buffer/service/logger.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/path_manager.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/valuebuffer_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gfx/geometry/point.h"
63 #include "ui/gfx/geometry/rect.h"
64 #include "ui/gfx/geometry/size.h"
65 #include "ui/gfx/overlay_transform.h"
66 #include "ui/gl/gl_bindings.h"
67 #include "ui/gl/gl_context.h"
68 #include "ui/gl/gl_fence.h"
69 #include "ui/gl/gl_image.h"
70 #include "ui/gl/gl_implementation.h"
71 #include "ui/gl/gl_surface.h"
72 #include "ui/gl/gl_version_info.h"
73 #include "ui/gl/gpu_timing.h"
75 #if defined(OS_MACOSX)
76 #include <IOSurface/IOSurface.h>
77 // Note that this must be included after gl_bindings.h to avoid conflicts.
78 #include <OpenGL/CGLIOSurface.h>
79 #endif
81 namespace gpu {
82 namespace gles2 {
84 namespace {
86 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
87 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
88 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
89 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
91 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
92 0.0f, 1.0f, 0.0f, 0.0f,
93 0.0f, 0.0f, 1.0f, 0.0f,
94 0.0f, 0.0f, 0.0f, 1.0f};
96 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
97 GLint rangeMax,
98 GLint precision) {
99 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
102 void GetShaderPrecisionFormatImpl(GLenum shader_type,
103 GLenum precision_type,
104 GLint* range, GLint* precision) {
105 switch (precision_type) {
106 case GL_LOW_INT:
107 case GL_MEDIUM_INT:
108 case GL_HIGH_INT:
109 // These values are for a 32-bit twos-complement integer format.
110 range[0] = 31;
111 range[1] = 30;
112 *precision = 0;
113 break;
114 case GL_LOW_FLOAT:
115 case GL_MEDIUM_FLOAT:
116 case GL_HIGH_FLOAT:
117 // These values are for an IEEE single-precision floating-point format.
118 range[0] = 127;
119 range[1] = 127;
120 *precision = 23;
121 break;
122 default:
123 NOTREACHED();
124 break;
127 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
128 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
129 // This function is sometimes defined even though it's really just
130 // a stub, so we need to set range and precision as if it weren't
131 // defined before calling it.
132 // On Mac OS with some GPUs, calling this generates a
133 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 // platforms.
135 glGetShaderPrecisionFormat(shader_type, precision_type,
136 range, precision);
138 // TODO(brianderson): Make the following official workarounds.
140 // Some drivers have bugs where they report the ranges as a negative number.
141 // Taking the absolute value here shouldn't hurt because negative numbers
142 // aren't expected anyway.
143 range[0] = abs(range[0]);
144 range[1] = abs(range[1]);
146 // If the driver reports a precision for highp float that isn't actually
147 // highp, don't pretend like it's supported because shader compilation will
148 // fail anyway.
149 if (precision_type == GL_HIGH_FLOAT &&
150 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
151 range[0] = 0;
152 range[1] = 0;
153 *precision = 0;
158 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
159 switch (plane_transform) {
160 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_NONE;
162 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
164 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
166 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
168 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
170 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
171 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
172 default:
173 return gfx::OVERLAY_TRANSFORM_INVALID;
177 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
178 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
179 DCHECK(manager);
180 GLuint client_id = 0;
181 if (object) {
182 manager->GetClientId(object->service_id(), &client_id);
184 return client_id;
187 struct Vec4f {
188 explicit Vec4f(const Vec4& data) {
189 data.GetValues(v);
192 GLfloat v[4];
195 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
196 // contains the other rectangle or shares an edge with the other rectangle.
197 bool CombineAdjacentRects(const gfx::Rect& rect1,
198 const gfx::Rect& rect2,
199 gfx::Rect* result) {
200 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
201 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
202 *result = rect2;
203 return true;
206 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
207 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
208 *result = rect1;
209 return true;
212 // Return the union of |rect1| and |rect2| if they share an edge.
213 if (rect1.SharesEdgeWith(rect2)) {
214 *result = gfx::UnionRects(rect1, rect2);
215 return true;
218 // Return false if it's not possible to combine |rect1| and |rect2|.
219 return false;
222 } // namespace
224 class GLES2DecoderImpl;
226 // Local versions of the SET_GL_ERROR macros
227 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
228 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
229 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
230 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
231 function_name, value, label)
232 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
233 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
234 function_name, pname)
235 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
236 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
237 function_name)
238 #define LOCAL_PEEK_GL_ERROR(function_name) \
239 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
240 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
241 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
242 #define LOCAL_PERFORMANCE_WARNING(msg) \
243 PerformanceWarning(__FILE__, __LINE__, msg)
244 #define LOCAL_RENDER_WARNING(msg) \
245 RenderWarning(__FILE__, __LINE__, msg)
247 // Check that certain assumptions the code makes are true. There are places in
248 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
249 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
250 // a few others) are 32bits. If they are not 32bits the code will have to change
251 // to call those GL functions with service side memory and then copy the results
252 // to shared memory, converting the sizes.
253 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
254 "GLint should be the same size as uint32");
255 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
256 "GLsizei should be the same size as uint32");
257 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
258 "GLfloat should be the same size as float");
260 // TODO(kbr): the use of this anonymous namespace core dumps the
261 // linker on Mac OS X 10.6 when the symbol ordering file is used
262 // namespace {
264 // Returns the address of the first byte after a struct.
265 template <typename T>
266 const void* AddressAfterStruct(const T& pod) {
267 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
270 // Returns the address of the frst byte after the struct or NULL if size >
271 // immediate_data_size.
272 template <typename RETURN_TYPE, typename COMMAND_TYPE>
273 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
274 uint32 size,
275 uint32 immediate_data_size) {
276 return (size <= immediate_data_size) ?
277 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
278 NULL;
281 // Computes the data size for certain gl commands like glUniform.
282 bool ComputeDataSize(
283 GLuint count,
284 size_t size,
285 unsigned int elements_per_unit,
286 uint32* dst) {
287 uint32 value;
288 if (!SafeMultiplyUint32(count, size, &value)) {
289 return false;
291 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
292 return false;
294 *dst = value;
295 return true;
298 // Return true if a character belongs to the ASCII subset as defined in
299 // GLSL ES 1.0 spec section 3.1.
300 static bool CharacterIsValidForGLES(unsigned char c) {
301 // Printing characters are valid except " $ ` @ \ ' DEL.
302 if (c >= 32 && c <= 126 &&
303 c != '"' &&
304 c != '$' &&
305 c != '`' &&
306 c != '@' &&
307 c != '\\' &&
308 c != '\'') {
309 return true;
311 // Horizontal tab, line feed, vertical tab, form feed, carriage return
312 // are also valid.
313 if (c >= 9 && c <= 13) {
314 return true;
317 return false;
320 static bool StringIsValidForGLES(const char* str) {
321 for (; *str; ++str) {
322 if (!CharacterIsValidForGLES(*str)) {
323 return false;
326 return true;
329 // This class prevents any GL errors that occur when it is in scope from
330 // being reported to the client.
331 class ScopedGLErrorSuppressor {
332 public:
333 explicit ScopedGLErrorSuppressor(
334 const char* function_name, ErrorState* error_state);
335 ~ScopedGLErrorSuppressor();
336 private:
337 const char* function_name_;
338 ErrorState* error_state_;
339 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
342 // Temporarily changes a decoder's bound texture and restore it when this
343 // object goes out of scope. Also temporarily switches to using active texture
344 // unit zero in case the client has changed that to something invalid.
345 class ScopedTextureBinder {
346 public:
347 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
348 ~ScopedTextureBinder();
350 private:
351 ContextState* state_;
352 GLenum target_;
353 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
356 // Temporarily changes a decoder's bound render buffer and restore it when this
357 // object goes out of scope.
358 class ScopedRenderBufferBinder {
359 public:
360 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
361 ~ScopedRenderBufferBinder();
363 private:
364 ContextState* state_;
365 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
368 // Temporarily changes a decoder's bound frame buffer and restore it when this
369 // object goes out of scope.
370 class ScopedFrameBufferBinder {
371 public:
372 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
373 ~ScopedFrameBufferBinder();
375 private:
376 GLES2DecoderImpl* decoder_;
377 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
380 // Temporarily changes a decoder's bound frame buffer to a resolved version of
381 // the multisampled offscreen render buffer if that buffer is multisampled, and,
382 // if it is bound or enforce_internal_framebuffer is true. If internal is
383 // true, the resolved framebuffer is not visible to the parent.
384 class ScopedResolvedFrameBufferBinder {
385 public:
386 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
387 bool enforce_internal_framebuffer,
388 bool internal);
389 ~ScopedResolvedFrameBufferBinder();
391 private:
392 GLES2DecoderImpl* decoder_;
393 bool resolve_and_bind_;
394 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
397 class ScopedModifyPixels {
398 public:
399 explicit ScopedModifyPixels(TextureRef* ref);
400 ~ScopedModifyPixels();
402 private:
403 TextureRef* ref_;
406 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
407 if (ref_)
408 ref_->texture()->OnWillModifyPixels();
411 ScopedModifyPixels::~ScopedModifyPixels() {
412 if (ref_)
413 ref_->texture()->OnDidModifyPixels();
416 class ScopedRenderTo {
417 public:
418 explicit ScopedRenderTo(Framebuffer* framebuffer);
419 ~ScopedRenderTo();
421 private:
422 const Framebuffer* framebuffer_;
425 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
426 : framebuffer_(framebuffer) {
427 if (framebuffer)
428 framebuffer_->OnWillRenderTo();
431 ScopedRenderTo::~ScopedRenderTo() {
432 if (framebuffer_)
433 framebuffer_->OnDidRenderTo();
436 // Encapsulates an OpenGL texture.
437 class BackTexture {
438 public:
439 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
440 ~BackTexture();
442 // Create a new render texture.
443 void Create();
445 // Set the initial size and format of a render texture or resize it.
446 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
448 // Copy the contents of the currently bound frame buffer.
449 void Copy(const gfx::Size& size, GLenum format);
451 // Destroy the render texture. This must be explicitly called before
452 // destroying this object.
453 void Destroy();
455 // Invalidate the texture. This can be used when a context is lost and it is
456 // not possible to make it current in order to free the resource.
457 void Invalidate();
459 GLuint id() const {
460 return id_;
463 gfx::Size size() const {
464 return size_;
467 private:
468 MemoryTypeTracker memory_tracker_;
469 ContextState* state_;
470 size_t bytes_allocated_;
471 GLuint id_;
472 gfx::Size size_;
473 DISALLOW_COPY_AND_ASSIGN(BackTexture);
476 // Encapsulates an OpenGL render buffer of any format.
477 class BackRenderbuffer {
478 public:
479 explicit BackRenderbuffer(
480 RenderbufferManager* renderbuffer_manager,
481 MemoryTracker* memory_tracker,
482 ContextState* state);
483 ~BackRenderbuffer();
485 // Create a new render buffer.
486 void Create();
488 // Set the initial size and format of a render buffer or resize it.
489 bool AllocateStorage(const FeatureInfo* feature_info,
490 const gfx::Size& size,
491 GLenum format,
492 GLsizei samples);
494 // Destroy the render buffer. This must be explicitly called before destroying
495 // this object.
496 void Destroy();
498 // Invalidate the render buffer. This can be used when a context is lost and
499 // it is not possible to make it current in order to free the resource.
500 void Invalidate();
502 GLuint id() const {
503 return id_;
506 private:
507 RenderbufferManager* renderbuffer_manager_;
508 MemoryTypeTracker memory_tracker_;
509 ContextState* state_;
510 size_t bytes_allocated_;
511 GLuint id_;
512 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
515 // Encapsulates an OpenGL frame buffer.
516 class BackFramebuffer {
517 public:
518 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
519 ~BackFramebuffer();
521 // Create a new frame buffer.
522 void Create();
524 // Attach a color render buffer to a frame buffer.
525 void AttachRenderTexture(BackTexture* texture);
527 // Attach a render buffer to a frame buffer. Note that this unbinds any
528 // currently bound frame buffer.
529 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
531 // Destroy the frame buffer. This must be explicitly called before destroying
532 // this object.
533 void Destroy();
535 // Invalidate the frame buffer. This can be used when a context is lost and it
536 // is not possible to make it current in order to free the resource.
537 void Invalidate();
539 // See glCheckFramebufferStatusEXT.
540 GLenum CheckStatus();
542 GLuint id() const {
543 return id_;
546 private:
547 GLES2DecoderImpl* decoder_;
548 GLuint id_;
549 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
552 struct FenceCallback {
553 FenceCallback()
554 : fence(gfx::GLFence::Create()) {
555 DCHECK(fence);
557 std::vector<base::Closure> callbacks;
558 scoped_ptr<gfx::GLFence> fence;
561 class AsyncUploadTokenCompletionObserver
562 : public AsyncPixelTransferCompletionObserver {
563 public:
564 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
565 : async_upload_token_(async_upload_token) {
568 void DidComplete(const AsyncMemoryParams& mem_params) override {
569 DCHECK(mem_params.buffer().get());
570 void* data = mem_params.GetDataAddress();
571 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
572 sync->SetAsyncUploadToken(async_upload_token_);
575 private:
576 ~AsyncUploadTokenCompletionObserver() override {}
578 uint32 async_upload_token_;
580 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
583 // } // anonymous namespace.
585 // static
586 const unsigned int GLES2Decoder::kDefaultStencilMask =
587 static_cast<unsigned int>(-1);
589 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
590 uint32* service_texture_id) {
591 return false;
594 GLES2Decoder::GLES2Decoder()
595 : initialized_(false),
596 debug_(false),
597 log_commands_(false),
598 unsafe_es3_apis_enabled_(false) {
601 GLES2Decoder::~GLES2Decoder() {
604 void GLES2Decoder::BeginDecoding() {}
606 void GLES2Decoder::EndDecoding() {}
608 // This class implements GLES2Decoder so we don't have to expose all the GLES2
609 // cmd stuff to outside this class.
610 class GLES2DecoderImpl : public GLES2Decoder,
611 public FramebufferManager::TextureDetachObserver,
612 public ErrorStateClient {
613 public:
614 explicit GLES2DecoderImpl(ContextGroup* group);
615 ~GLES2DecoderImpl() override;
617 // Overridden from AsyncAPIInterface.
618 Error DoCommand(unsigned int command,
619 unsigned int arg_count,
620 const void* args) override;
622 error::Error DoCommands(unsigned int num_commands,
623 const void* buffer,
624 int num_entries,
625 int* entries_processed) override;
627 template <bool DebugImpl>
628 error::Error DoCommandsImpl(unsigned int num_commands,
629 const void* buffer,
630 int num_entries,
631 int* entries_processed);
633 // Overridden from AsyncAPIInterface.
634 const char* GetCommandName(unsigned int command_id) const override;
636 // Overridden from GLES2Decoder.
637 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
638 const scoped_refptr<gfx::GLContext>& context,
639 bool offscreen,
640 const gfx::Size& offscreen_size,
641 const DisallowedFeatures& disallowed_features,
642 const std::vector<int32>& attribs) override;
643 void Destroy(bool have_context) override;
644 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
645 void ProduceFrontBuffer(const Mailbox& mailbox) override;
646 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
647 void UpdateParentTextureInfo();
648 bool MakeCurrent() override;
649 GLES2Util* GetGLES2Util() override { return &util_; }
650 gfx::GLContext* GetGLContext() override { return context_.get(); }
651 ContextGroup* GetContextGroup() override { return group_.get(); }
652 Capabilities GetCapabilities() override;
653 void RestoreState(const ContextState* prev_state) override;
655 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
656 void RestoreAllTextureUnitBindings(
657 const ContextState* prev_state) const override {
658 state_.RestoreAllTextureUnitBindings(prev_state);
660 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
661 state_.RestoreActiveTextureUnitBinding(target);
663 void RestoreBufferBindings() const override {
664 state_.RestoreBufferBindings();
666 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
667 void RestoreProgramBindings() const override {
668 state_.RestoreProgramBindings();
670 void RestoreTextureUnitBindings(unsigned unit) const override {
671 state_.RestoreTextureUnitBindings(unit, NULL);
673 void RestoreFramebufferBindings() const override;
674 void RestoreRenderbufferBindings() override;
675 void RestoreTextureState(unsigned service_id) const override;
677 void ClearAllAttributes() const override;
678 void RestoreAllAttributes() const override;
680 QueryManager* GetQueryManager() override { return query_manager_.get(); }
681 VertexArrayManager* GetVertexArrayManager() override {
682 return vertex_array_manager_.get();
684 ImageManager* GetImageManager() override { return image_manager_.get(); }
686 ValuebufferManager* GetValuebufferManager() override {
687 return valuebuffer_manager();
690 bool ProcessPendingQueries(bool did_finish) override;
692 bool HasMoreIdleWork() override;
693 void PerformIdleWork() override;
695 void WaitForReadPixels(base::Closure callback) override;
697 void SetResizeCallback(
698 const base::Callback<void(gfx::Size, float)>& callback) override;
700 Logger* GetLogger() override;
702 void BeginDecoding() override;
703 void EndDecoding() override;
705 ErrorState* GetErrorState() override;
706 const ContextState* GetContextState() override { return &state_; }
708 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
709 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
711 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
712 void ResetAsyncPixelTransferManagerForTest() override;
713 void SetAsyncPixelTransferManagerForTest(
714 AsyncPixelTransferManager* manager) override;
715 void SetIgnoreCachedStateForTest(bool ignore) override;
716 void ProcessFinishedAsyncTransfers();
718 bool GetServiceTextureId(uint32 client_texture_id,
719 uint32* service_texture_id) override;
721 uint32 GetTextureUploadCount() override;
722 base::TimeDelta GetTotalTextureUploadTime() override;
723 base::TimeDelta GetTotalProcessingCommandsTime() override;
724 void AddProcessingCommandsTime(base::TimeDelta) override;
726 // Restores the current state to the user's settings.
727 void RestoreCurrentFramebufferBindings();
729 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
730 void ApplyDirtyState();
732 // These check the state of the currently bound framebuffer or the
733 // backbuffer if no framebuffer is bound.
734 // Check with all attached and enabled color attachments.
735 bool BoundFramebufferHasColorAttachmentWithAlpha();
736 bool BoundFramebufferHasDepthAttachment();
737 bool BoundFramebufferHasStencilAttachment();
739 error::ContextLostReason GetContextLostReason() override;
741 // Overridden from FramebufferManager::TextureDetachObserver:
742 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
744 // Overriden from ErrorStateClient.
745 void OnContextLostError() override;
746 void OnOutOfMemoryError() override;
748 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
749 void EnsureRenderbufferBound();
751 // Helpers to facilitate calling into compatible extensions.
752 static void RenderbufferStorageMultisampleHelper(
753 const FeatureInfo* feature_info,
754 GLenum target,
755 GLsizei samples,
756 GLenum internal_format,
757 GLsizei width,
758 GLsizei height);
760 void BlitFramebufferHelper(GLint srcX0,
761 GLint srcY0,
762 GLint srcX1,
763 GLint srcY1,
764 GLint dstX0,
765 GLint dstY0,
766 GLint dstX1,
767 GLint dstY1,
768 GLbitfield mask,
769 GLenum filter);
771 private:
772 friend class ScopedFrameBufferBinder;
773 friend class ScopedResolvedFrameBufferBinder;
774 friend class BackFramebuffer;
776 // Initialize or re-initialize the shader translator.
777 bool InitializeShaderTranslator();
779 void UpdateCapabilities();
781 // Helpers for the glGen and glDelete functions.
782 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
783 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
784 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
785 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
786 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
787 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
788 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
789 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
790 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
791 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
792 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
793 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
794 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
795 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
796 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
797 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
799 // Helper for async upload token completion notification callback.
800 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
801 uint32 sync_data_shm_id,
802 uint32 sync_data_shm_offset);
806 // Workarounds
807 void OnFboChanged() const;
808 void OnUseFramebuffer() const;
810 error::ContextLostReason GetContextLostReasonFromResetStatus(
811 GLenum reset_status) const;
813 // TODO(gman): Cache these pointers?
814 BufferManager* buffer_manager() {
815 return group_->buffer_manager();
818 RenderbufferManager* renderbuffer_manager() {
819 return group_->renderbuffer_manager();
822 FramebufferManager* framebuffer_manager() {
823 return group_->framebuffer_manager();
826 ValuebufferManager* valuebuffer_manager() {
827 return group_->valuebuffer_manager();
830 PathManager* path_manager() { return group_->path_manager(); }
832 ProgramManager* program_manager() {
833 return group_->program_manager();
836 ShaderManager* shader_manager() {
837 return group_->shader_manager();
840 ShaderTranslatorCache* shader_translator_cache() {
841 return group_->shader_translator_cache();
844 const TextureManager* texture_manager() const {
845 return group_->texture_manager();
848 TextureManager* texture_manager() {
849 return group_->texture_manager();
852 MailboxManager* mailbox_manager() {
853 return group_->mailbox_manager();
856 ImageManager* image_manager() { return image_manager_.get(); }
858 VertexArrayManager* vertex_array_manager() {
859 return vertex_array_manager_.get();
862 MemoryTracker* memory_tracker() {
863 return group_->memory_tracker();
866 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
867 MemoryTracker* tracker = memory_tracker();
868 if (tracker) {
869 return tracker->EnsureGPUMemoryAvailable(estimated_size);
871 return true;
874 bool IsWebGLContext() const {
875 return webgl_version_ == 1 || webgl_version_ == 2;
878 bool IsOffscreenBufferMultisampled() const {
879 return offscreen_target_samples_ > 1;
882 // Creates a Texture for the given texture.
883 TextureRef* CreateTexture(
884 GLuint client_id, GLuint service_id) {
885 return texture_manager()->CreateTexture(client_id, service_id);
888 // Gets the texture info for the given texture. Returns NULL if none exists.
889 TextureRef* GetTexture(GLuint client_id) const {
890 return texture_manager()->GetTexture(client_id);
893 // Deletes the texture info for the given texture.
894 void RemoveTexture(GLuint client_id) {
895 texture_manager()->RemoveTexture(client_id);
898 // Get the size (in pixels) of the currently bound frame buffer (either FBO
899 // or regular back buffer).
900 gfx::Size GetBoundReadFrameBufferSize();
902 // Get the format/type of the currently bound frame buffer (either FBO or
903 // regular back buffer).
904 // If the color image is a renderbuffer, returns 0 for type.
905 GLenum GetBoundReadFrameBufferTextureType();
906 GLenum GetBoundReadFrameBufferInternalFormat();
908 // Wrapper for CompressedTexImage2D commands.
909 error::Error DoCompressedTexImage2D(
910 GLenum target,
911 GLint level,
912 GLenum internal_format,
913 GLsizei width,
914 GLsizei height,
915 GLint border,
916 GLsizei image_size,
917 const void* data);
919 // Wrapper for CompressedTexImage3D commands.
920 error::Error DoCompressedTexImage3D(
921 GLenum target,
922 GLint level,
923 GLenum internal_format,
924 GLsizei width,
925 GLsizei height,
926 GLsizei depth,
927 GLint border,
928 GLsizei image_size,
929 const void* data);
931 // Wrapper for CompressedTexSubImage2D.
932 void DoCompressedTexSubImage2D(
933 GLenum target,
934 GLint level,
935 GLint xoffset,
936 GLint yoffset,
937 GLsizei width,
938 GLsizei height,
939 GLenum format,
940 GLsizei imageSize,
941 const void * data);
943 // Wrapper for CompressedTexSubImage3D.
944 void DoCompressedTexSubImage3D(
945 GLenum target,
946 GLint level,
947 GLint xoffset,
948 GLint yoffset,
949 GLint zoffset,
950 GLsizei width,
951 GLsizei height,
952 GLsizei depth,
953 GLenum format,
954 GLsizei image_size,
955 const void* data);
957 // Wrapper for CopyTexImage2D.
958 void DoCopyTexImage2D(
959 GLenum target,
960 GLint level,
961 GLenum internal_format,
962 GLint x,
963 GLint y,
964 GLsizei width,
965 GLsizei height,
966 GLint border);
968 // Wrapper for SwapBuffers.
969 void DoSwapBuffers();
971 // Wrapper for SwapInterval.
972 void DoSwapInterval(int interval);
974 // Wrapper for CopyTexSubImage2D.
975 void DoCopyTexSubImage2D(
976 GLenum target,
977 GLint level,
978 GLint xoffset,
979 GLint yoffset,
980 GLint x,
981 GLint y,
982 GLsizei width,
983 GLsizei height);
985 // Validation for TexSubImage2D.
986 bool ValidateTexSubImage2D(
987 error::Error* error,
988 const char* function_name,
989 GLenum target,
990 GLint level,
991 GLint xoffset,
992 GLint yoffset,
993 GLsizei width,
994 GLsizei height,
995 GLenum format,
996 GLenum type,
997 const void * data);
999 // Wrapper for TexSubImage2D.
1000 error::Error DoTexSubImage2D(
1001 GLenum target,
1002 GLint level,
1003 GLint xoffset,
1004 GLint yoffset,
1005 GLsizei width,
1006 GLsizei height,
1007 GLenum format,
1008 GLenum type,
1009 const void * data);
1011 // Wrapper for TexSubImage3D.
1012 error::Error DoTexSubImage3D(
1013 GLenum target,
1014 GLint level,
1015 GLint xoffset,
1016 GLint yoffset,
1017 GLint zoffset,
1018 GLsizei width,
1019 GLsizei height,
1020 GLsizei depth,
1021 GLenum format,
1022 GLenum type,
1023 const void * data);
1025 // Extra validation for async tex(Sub)Image2D.
1026 bool ValidateAsyncTransfer(
1027 const char* function_name,
1028 TextureRef* texture_ref,
1029 GLenum target,
1030 GLint level,
1031 const void * data);
1033 // Wrapper for TexImageIOSurface2DCHROMIUM.
1034 void DoTexImageIOSurface2DCHROMIUM(
1035 GLenum target,
1036 GLsizei width,
1037 GLsizei height,
1038 GLuint io_surface_id,
1039 GLuint plane);
1041 void DoCopyTextureCHROMIUM(GLenum target,
1042 GLuint source_id,
1043 GLuint dest_id,
1044 GLenum internal_format,
1045 GLenum dest_type,
1046 GLboolean unpack_flip_y,
1047 GLboolean unpack_premultiply_alpha,
1048 GLboolean unpack_unmultiply_alpha);
1050 void DoCopySubTextureCHROMIUM(GLenum target,
1051 GLuint source_id,
1052 GLuint dest_id,
1053 GLint xoffset,
1054 GLint yoffset,
1055 GLint x,
1056 GLint y,
1057 GLsizei width,
1058 GLsizei height,
1059 GLboolean unpack_flip_y,
1060 GLboolean unpack_premultiply_alpha,
1061 GLboolean unpack_unmultiply_alpha);
1063 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1064 GLuint source_id,
1065 GLuint dest_id);
1067 // Wrapper for TexStorage2DEXT.
1068 void DoTexStorage2DEXT(
1069 GLenum target,
1070 GLint levels,
1071 GLenum internal_format,
1072 GLsizei width,
1073 GLsizei height);
1075 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1076 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1077 const GLbyte* key);
1078 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1079 GLenum target, const GLbyte* data);
1081 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1082 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1083 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1084 GLuint client_id);
1086 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1087 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1088 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1089 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1090 void DoUniformValueBufferCHROMIUM(GLint location,
1091 GLenum target,
1092 GLenum subscription);
1094 void DoBindTexImage2DCHROMIUM(
1095 GLenum target,
1096 GLint image_id);
1097 void DoReleaseTexImage2DCHROMIUM(
1098 GLenum target,
1099 GLint image_id);
1101 void DoTraceEndCHROMIUM(void);
1103 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1105 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1107 void DoFlushDriverCachesCHROMIUM(void);
1109 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1110 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1112 // Creates a Program for the given program.
1113 Program* CreateProgram(
1114 GLuint client_id, GLuint service_id) {
1115 return program_manager()->CreateProgram(client_id, service_id);
1118 // Gets the program info for the given program. Returns NULL if none exists.
1119 Program* GetProgram(GLuint client_id) {
1120 return program_manager()->GetProgram(client_id);
1123 #if defined(NDEBUG)
1124 void LogClientServiceMapping(
1125 const char* /* function_name */,
1126 GLuint /* client_id */,
1127 GLuint /* service_id */) {
1129 template<typename T>
1130 void LogClientServiceForInfo(
1131 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1133 #else
1134 void LogClientServiceMapping(
1135 const char* function_name, GLuint client_id, GLuint service_id) {
1136 if (service_logging_) {
1137 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1138 << ": client_id = " << client_id
1139 << ", service_id = " << service_id;
1142 template<typename T>
1143 void LogClientServiceForInfo(
1144 T* info, GLuint client_id, const char* function_name) {
1145 if (info) {
1146 LogClientServiceMapping(function_name, client_id, info->service_id());
1149 #endif
1151 // Gets the program info for the given program. If it's not a program
1152 // generates a GL error. Returns NULL if not program.
1153 Program* GetProgramInfoNotShader(
1154 GLuint client_id, const char* function_name) {
1155 Program* program = GetProgram(client_id);
1156 if (!program) {
1157 if (GetShader(client_id)) {
1158 LOCAL_SET_GL_ERROR(
1159 GL_INVALID_OPERATION, function_name, "shader passed for program");
1160 } else {
1161 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1164 LogClientServiceForInfo(program, client_id, function_name);
1165 return program;
1169 // Creates a Shader for the given shader.
1170 Shader* CreateShader(
1171 GLuint client_id,
1172 GLuint service_id,
1173 GLenum shader_type) {
1174 return shader_manager()->CreateShader(
1175 client_id, service_id, shader_type);
1178 // Gets the shader info for the given shader. Returns NULL if none exists.
1179 Shader* GetShader(GLuint client_id) {
1180 return shader_manager()->GetShader(client_id);
1183 // Gets the shader info for the given shader. If it's not a shader generates a
1184 // GL error. Returns NULL if not shader.
1185 Shader* GetShaderInfoNotProgram(
1186 GLuint client_id, const char* function_name) {
1187 Shader* shader = GetShader(client_id);
1188 if (!shader) {
1189 if (GetProgram(client_id)) {
1190 LOCAL_SET_GL_ERROR(
1191 GL_INVALID_OPERATION, function_name, "program passed for shader");
1192 } else {
1193 LOCAL_SET_GL_ERROR(
1194 GL_INVALID_VALUE, function_name, "unknown shader");
1197 LogClientServiceForInfo(shader, client_id, function_name);
1198 return shader;
1201 // Creates a buffer info for the given buffer.
1202 void CreateBuffer(GLuint client_id, GLuint service_id) {
1203 return buffer_manager()->CreateBuffer(client_id, service_id);
1206 // Gets the buffer info for the given buffer.
1207 Buffer* GetBuffer(GLuint client_id) {
1208 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1209 return buffer;
1212 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1213 // on glDeleteBuffers so we can make sure the user does not try to render
1214 // with deleted buffers.
1215 void RemoveBuffer(GLuint client_id);
1217 // Creates a framebuffer info for the given framebuffer.
1218 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1219 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1222 // Gets the framebuffer info for the given framebuffer.
1223 Framebuffer* GetFramebuffer(GLuint client_id) {
1224 return framebuffer_manager()->GetFramebuffer(client_id);
1227 // Removes the framebuffer info for the given framebuffer.
1228 void RemoveFramebuffer(GLuint client_id) {
1229 framebuffer_manager()->RemoveFramebuffer(client_id);
1232 // Creates a renderbuffer info for the given renderbuffer.
1233 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1234 return renderbuffer_manager()->CreateRenderbuffer(
1235 client_id, service_id);
1238 // Gets the renderbuffer info for the given renderbuffer.
1239 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1240 return renderbuffer_manager()->GetRenderbuffer(client_id);
1243 // Removes the renderbuffer info for the given renderbuffer.
1244 void RemoveRenderbuffer(GLuint client_id) {
1245 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1248 // Creates a valuebuffer info for the given valuebuffer.
1249 void CreateValuebuffer(GLuint client_id) {
1250 return valuebuffer_manager()->CreateValuebuffer(client_id);
1253 // Gets the valuebuffer info for a given valuebuffer.
1254 Valuebuffer* GetValuebuffer(GLuint client_id) {
1255 return valuebuffer_manager()->GetValuebuffer(client_id);
1258 // Removes the valuebuffer info for the given valuebuffer.
1259 void RemoveValuebuffer(GLuint client_id) {
1260 valuebuffer_manager()->RemoveValuebuffer(client_id);
1263 // Gets the vertex attrib manager for the given vertex array.
1264 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1265 VertexAttribManager* info =
1266 vertex_array_manager()->GetVertexAttribManager(client_id);
1267 return info;
1270 // Removes the vertex attrib manager for the given vertex array.
1271 void RemoveVertexAttribManager(GLuint client_id) {
1272 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1275 // Creates a vertex attrib manager for the given vertex array.
1276 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1277 GLuint client_id,
1278 GLuint service_id,
1279 bool client_visible) {
1280 return vertex_array_manager()->CreateVertexAttribManager(
1281 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1284 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1285 void DoBindUniformLocationCHROMIUM(
1286 GLuint client_id, GLint location, const char* name);
1288 error::Error GetAttribLocationHelper(
1289 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1290 const std::string& name_str);
1292 error::Error GetUniformLocationHelper(
1293 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1294 const std::string& name_str);
1296 error::Error GetFragDataLocationHelper(
1297 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1298 const std::string& name_str);
1300 // Wrapper for glShaderSource.
1301 void DoShaderSource(
1302 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1304 // Wrapper for glTransformFeedbackVaryings.
1305 void DoTransformFeedbackVaryings(
1306 GLuint client_program_id, GLsizei count, const char* const* varyings,
1307 GLenum buffer_mode);
1309 // Clear any textures used by the current program.
1310 bool ClearUnclearedTextures();
1312 // Clears any uncleared attachments attached to the given frame buffer.
1313 // Returns false if there was a generated GL error.
1314 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1316 // overridden from GLES2Decoder
1317 bool ClearLevel(Texture* texture,
1318 unsigned target,
1319 int level,
1320 unsigned format,
1321 unsigned type,
1322 int xoffset,
1323 int yoffset,
1324 int width,
1325 int height) override;
1327 // Restore all GL state that affects clearing.
1328 void RestoreClearState();
1330 // Remembers the state of some capabilities.
1331 // Returns: true if glEnable/glDisable should actually be called.
1332 bool SetCapabilityState(GLenum cap, bool enabled);
1334 // Check that the currently bound framebuffers are valid.
1335 // Generates GL error if not.
1336 bool CheckBoundFramebuffersValid(const char* func_name);
1338 // Check that the currently bound read framebuffer has a color image
1339 // attached. Generates GL error if not.
1340 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1342 // Check that the currently bound read framebuffer's color image
1343 // isn't the target texture of the glCopyTex{Sub}Image2D.
1344 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1346 // Check if a framebuffer meets our requirements.
1347 bool CheckFramebufferValid(
1348 Framebuffer* framebuffer,
1349 GLenum target,
1350 const char* func_name);
1352 // Check if the current valuebuffer exists and is valid. If not generates
1353 // the appropriate GL error. Returns true if the current valuebuffer is in
1354 // a usable state.
1355 bool CheckCurrentValuebuffer(const char* function_name);
1357 // Check if the current valuebuffer exists and is valiud and that the
1358 // value buffer is actually subscribed to the given subscription
1359 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1360 const char* function_name);
1362 // Check if the location can be used for the given subscription target. If not
1363 // generates the appropriate GL error. Returns true if the location is usable
1364 bool CheckSubscriptionTarget(GLint location,
1365 GLenum subscription,
1366 const char* function_name);
1368 // Checks if the current program exists and is valid. If not generates the
1369 // appropriate GL error. Returns true if the current program is in a usable
1370 // state.
1371 bool CheckCurrentProgram(const char* function_name);
1373 // Checks if the current program exists and is valid and that location is not
1374 // -1. If the current program is not valid generates the appropriate GL
1375 // error. Returns true if the current program is in a usable state and
1376 // location is not -1.
1377 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1379 // Checks if the current program samples a texture that is also the color
1380 // image of the current bound framebuffer, i.e., the source and destination
1381 // of the draw operation are the same.
1382 bool CheckDrawingFeedbackLoops();
1384 // Checks if |api_type| is valid for the given uniform
1385 // If the api type is not valid generates the appropriate GL
1386 // error. Returns true if |api_type| is valid for the uniform
1387 bool CheckUniformForApiType(const Program::UniformInfo* info,
1388 const char* function_name,
1389 Program::UniformApiType api_type);
1391 // Gets the type of a uniform for a location in the current program. Sets GL
1392 // errors if the current program is not valid. Returns true if the current
1393 // program is valid and the location exists. Adjusts count so it
1394 // does not overflow the uniform.
1395 bool PrepForSetUniformByLocation(GLint fake_location,
1396 const char* function_name,
1397 Program::UniformApiType api_type,
1398 GLint* real_location,
1399 GLenum* type,
1400 GLsizei* count);
1402 // Gets the service id for any simulated backbuffer fbo.
1403 GLuint GetBackbufferServiceId() const;
1405 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1406 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1408 // Helper for glGetVertexAttrib
1409 void GetVertexAttribHelper(
1410 const VertexAttrib* attrib, GLenum pname, GLint* param);
1412 // Wrapper for glActiveTexture
1413 void DoActiveTexture(GLenum texture_unit);
1415 // Wrapper for glAttachShader
1416 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1418 // Wrapper for glBindBuffer since we need to track the current targets.
1419 void DoBindBuffer(GLenum target, GLuint buffer);
1421 // Wrapper for glBindFramebuffer since we need to track the current targets.
1422 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1424 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1425 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1427 // Wrapper for glBindTexture since we need to track the current targets.
1428 void DoBindTexture(GLenum target, GLuint texture);
1430 // Wrapper for glBindVertexArrayOES
1431 void DoBindVertexArrayOES(GLuint array);
1432 void EmulateVertexArrayState();
1434 // Wrapper for glBlitFramebufferCHROMIUM.
1435 void DoBlitFramebufferCHROMIUM(
1436 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1437 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1438 GLbitfield mask, GLenum filter);
1440 // Wrapper for glBufferSubData.
1441 void DoBufferSubData(
1442 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1444 // Wrapper for glCheckFramebufferStatus
1445 GLenum DoCheckFramebufferStatus(GLenum target);
1447 // Wrapper for glClear
1448 error::Error DoClear(GLbitfield mask);
1450 // Wrappers for various state.
1451 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1452 void DoSampleCoverage(GLclampf value, GLboolean invert);
1454 // Wrapper for glCompileShader.
1455 void DoCompileShader(GLuint shader);
1457 // Wrapper for glDetachShader
1458 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1460 // Wrapper for glDisable
1461 void DoDisable(GLenum cap);
1463 // Wrapper for glDisableVertexAttribArray.
1464 void DoDisableVertexAttribArray(GLuint index);
1466 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1467 // attachments.
1468 void DoDiscardFramebufferEXT(GLenum target,
1469 GLsizei numAttachments,
1470 const GLenum* attachments);
1472 // Wrapper for glEnable
1473 void DoEnable(GLenum cap);
1475 // Wrapper for glEnableVertexAttribArray.
1476 void DoEnableVertexAttribArray(GLuint index);
1478 // Wrapper for glFinish.
1479 void DoFinish();
1481 // Wrapper for glFlush.
1482 void DoFlush();
1484 // Wrapper for glFramebufferRenderbufffer.
1485 void DoFramebufferRenderbuffer(
1486 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1487 GLuint renderbuffer);
1489 // Wrapper for glFramebufferTexture2D.
1490 void DoFramebufferTexture2D(
1491 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1492 GLint level);
1494 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1495 void DoFramebufferTexture2DMultisample(
1496 GLenum target, GLenum attachment, GLenum textarget,
1497 GLuint texture, GLint level, GLsizei samples);
1499 // Common implementation for both DoFramebufferTexture2D wrappers.
1500 void DoFramebufferTexture2DCommon(const char* name,
1501 GLenum target, GLenum attachment, GLenum textarget,
1502 GLuint texture, GLint level, GLsizei samples);
1504 // Wrapper for glFramebufferTextureLayer.
1505 void DoFramebufferTextureLayer(
1506 GLenum target, GLenum attachment, GLuint texture, GLint level,
1507 GLint layer);
1509 // Wrapper for glGenerateMipmap
1510 void DoGenerateMipmap(GLenum target);
1512 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1513 // to account for different pname values defined in different extension
1514 // variants.
1515 GLenum AdjustGetPname(GLenum pname);
1517 // Wrapper for DoGetBooleanv.
1518 void DoGetBooleanv(GLenum pname, GLboolean* params);
1520 // Wrapper for DoGetFloatv.
1521 void DoGetFloatv(GLenum pname, GLfloat* params);
1523 // Wrapper for glGetFramebufferAttachmentParameteriv.
1524 void DoGetFramebufferAttachmentParameteriv(
1525 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1527 // Wrapper for glGetInteger64v.
1528 void DoGetInteger64v(GLenum pname, GLint64* params);
1530 // Wrapper for glGetIntegerv.
1531 void DoGetIntegerv(GLenum pname, GLint* params);
1533 // Gets the max value in a range in a buffer.
1534 GLuint DoGetMaxValueInBufferCHROMIUM(
1535 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1537 // Wrapper for glGetBufferParameteri64v.
1538 void DoGetBufferParameteri64v(
1539 GLenum target, GLenum pname, GLint64* params);
1541 // Wrapper for glGetBufferParameteriv.
1542 void DoGetBufferParameteriv(
1543 GLenum target, GLenum pname, GLint* params);
1545 // Wrapper for glGetProgramiv.
1546 void DoGetProgramiv(
1547 GLuint program_id, GLenum pname, GLint* params);
1549 // Wrapper for glRenderbufferParameteriv.
1550 void DoGetRenderbufferParameteriv(
1551 GLenum target, GLenum pname, GLint* params);
1553 // Wrapper for glGetShaderiv
1554 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1556 // Wrappers for glGetTexParameter.
1557 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1558 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1559 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1561 // Wrappers for glGetVertexAttrib.
1562 template <typename T>
1563 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1564 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1565 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1566 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1567 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1569 // Wrappers for glIsXXX functions.
1570 bool DoIsEnabled(GLenum cap);
1571 bool DoIsBuffer(GLuint client_id);
1572 bool DoIsFramebuffer(GLuint client_id);
1573 bool DoIsProgram(GLuint client_id);
1574 bool DoIsRenderbuffer(GLuint client_id);
1575 bool DoIsShader(GLuint client_id);
1576 bool DoIsTexture(GLuint client_id);
1577 bool DoIsVertexArrayOES(GLuint client_id);
1578 bool DoIsPathCHROMIUM(GLuint client_id);
1580 // Wrapper for glLinkProgram
1581 void DoLinkProgram(GLuint program);
1583 // Wrapper for glReadBuffer
1584 void DoReadBuffer(GLenum src);
1586 // Wrapper for glRenderbufferStorage.
1587 void DoRenderbufferStorage(
1588 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1590 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1591 void DoRenderbufferStorageMultisampleCHROMIUM(
1592 GLenum target, GLsizei samples, GLenum internalformat,
1593 GLsizei width, GLsizei height);
1595 // Handler for glRenderbufferStorageMultisampleEXT
1596 // (multisampled_render_to_texture).
1597 void DoRenderbufferStorageMultisampleEXT(
1598 GLenum target, GLsizei samples, GLenum internalformat,
1599 GLsizei width, GLsizei height);
1601 // Common validation for multisample extensions.
1602 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1603 GLenum internalformat,
1604 GLsizei width,
1605 GLsizei height);
1607 // Verifies that the currently bound multisample renderbuffer is valid
1608 // Very slow! Only done on platforms with driver bugs that return invalid
1609 // buffers under memory pressure
1610 bool VerifyMultisampleRenderbufferIntegrity(
1611 GLuint renderbuffer, GLenum format);
1613 // Wrapper for glReleaseShaderCompiler.
1614 void DoReleaseShaderCompiler() { }
1616 // Wrappers for glSamplerParameter*v functions.
1617 void DoSamplerParameterfv(
1618 GLuint sampler, GLenum pname, const GLfloat* params);
1619 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1621 // Wrappers for glTexParameter functions.
1622 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1623 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1624 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1625 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1627 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1628 // spec only these 2 functions can be used to set sampler uniforms.
1629 void DoUniform1i(GLint fake_location, GLint v0);
1630 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1631 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1632 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1633 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1635 // Wrappers for glUniformfv because some drivers don't correctly accept
1636 // bool uniforms.
1637 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1638 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1639 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1640 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1642 void DoUniformMatrix2fv(
1643 GLint fake_location, GLsizei count, GLboolean transpose,
1644 const GLfloat* value);
1645 void DoUniformMatrix3fv(
1646 GLint fake_location, GLsizei count, GLboolean transpose,
1647 const GLfloat* value);
1648 void DoUniformMatrix4fv(
1649 GLint fake_location, GLsizei count, GLboolean transpose,
1650 const GLfloat* value);
1652 template <typename T>
1653 bool SetVertexAttribValue(
1654 const char* function_name, GLuint index, const T* value);
1656 // Wrappers for glVertexAttrib??
1657 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1658 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1659 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1660 void DoVertexAttrib4f(
1661 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1662 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1663 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1664 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1665 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1666 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1667 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1668 void DoVertexAttribI4ui(
1669 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1670 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1672 // Wrapper for glViewport
1673 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1675 // Wrapper for glUseProgram
1676 void DoUseProgram(GLuint program);
1678 // Wrapper for glValidateProgram.
1679 void DoValidateProgram(GLuint program_client_id);
1681 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1682 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1683 void DoPopGroupMarkerEXT(void);
1685 // Gets the number of values that will be returned by glGetXXX. Returns
1686 // false if pname is unknown.
1687 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1689 // Checks if the current program and vertex attributes are valid for drawing.
1690 bool IsDrawValid(
1691 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1692 GLsizei primcount);
1694 // Returns true if successful, simulated will be true if attrib0 was
1695 // simulated.
1696 bool SimulateAttrib0(
1697 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1698 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1700 // If an image is bound to texture, this will call Will/DidUseTexImage
1701 // if needed.
1702 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1703 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1705 // Returns false if textures were replaced.
1706 bool PrepareTexturesForRender();
1707 void RestoreStateForTextures();
1709 // Returns true if GL_FIXED attribs were simulated.
1710 bool SimulateFixedAttribs(
1711 const char* function_name,
1712 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1713 void RestoreStateForSimulatedFixedAttribs();
1715 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1716 // cases (primcount is always 1 for non-instanced).
1717 error::Error DoDrawArrays(
1718 const char* function_name,
1719 bool instanced, GLenum mode, GLint first, GLsizei count,
1720 GLsizei primcount);
1721 error::Error DoDrawElements(
1722 const char* function_name,
1723 bool instanced, GLenum mode, GLsizei count, GLenum type,
1724 int32 offset, GLsizei primcount);
1726 GLenum GetBindTargetForSamplerType(GLenum type) {
1727 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1728 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1729 switch (type) {
1730 case GL_SAMPLER_2D:
1731 return GL_TEXTURE_2D;
1732 case GL_SAMPLER_CUBE:
1733 return GL_TEXTURE_CUBE_MAP;
1734 case GL_SAMPLER_EXTERNAL_OES:
1735 return GL_TEXTURE_EXTERNAL_OES;
1736 case GL_SAMPLER_2D_RECT_ARB:
1737 return GL_TEXTURE_RECTANGLE_ARB;
1740 NOTREACHED();
1741 return 0;
1744 // Gets the framebuffer info for a particular target.
1745 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1746 Framebuffer* framebuffer = NULL;
1747 switch (target) {
1748 case GL_FRAMEBUFFER:
1749 case GL_DRAW_FRAMEBUFFER_EXT:
1750 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1751 break;
1752 case GL_READ_FRAMEBUFFER_EXT:
1753 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1754 break;
1755 default:
1756 NOTREACHED();
1757 break;
1759 return framebuffer;
1762 Renderbuffer* GetRenderbufferInfoForTarget(
1763 GLenum target) {
1764 Renderbuffer* renderbuffer = NULL;
1765 switch (target) {
1766 case GL_RENDERBUFFER:
1767 renderbuffer = state_.bound_renderbuffer.get();
1768 break;
1769 default:
1770 NOTREACHED();
1771 break;
1773 return renderbuffer;
1776 // Validates the program and location for a glGetUniform call and returns
1777 // a SizeResult setup to receive the result. Returns true if glGetUniform
1778 // should be called.
1779 template <class T>
1780 bool GetUniformSetup(GLuint program,
1781 GLint fake_location,
1782 uint32 shm_id,
1783 uint32 shm_offset,
1784 error::Error* error,
1785 GLint* real_location,
1786 GLuint* service_id,
1787 SizedResult<T>** result,
1788 GLenum* result_type,
1789 GLsizei* result_size);
1791 bool WasContextLost() const override;
1792 bool WasContextLostByRobustnessExtension() const override;
1793 void MarkContextLost(error::ContextLostReason reason) override;
1794 bool CheckResetStatus();
1796 #if defined(OS_MACOSX)
1797 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1798 #endif
1800 bool GetCompressedTexSizeInBytes(
1801 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1802 GLenum format, GLsizei* size_in_bytes);
1804 bool ValidateCompressedTexDimensions(
1805 const char* function_name, GLenum target, GLint level,
1806 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1807 bool ValidateCompressedTexFuncData(
1808 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1809 GLenum format, GLsizei size);
1810 bool ValidateCompressedTexSubDimensions(
1811 const char* function_name,
1812 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1813 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1814 Texture* texture);
1815 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1816 GLenum target,
1817 TextureRef* source_texture_ref,
1818 TextureRef* dest_texture_ref,
1819 GLenum dest_internal_format);
1820 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1821 GLenum target,
1822 TextureRef* source_texture_ref,
1823 TextureRef* dest_texture_ref);
1825 void RenderWarning(const char* filename, int line, const std::string& msg);
1826 void PerformanceWarning(
1827 const char* filename, int line, const std::string& msg);
1829 const FeatureInfo::FeatureFlags& features() const {
1830 return feature_info_->feature_flags();
1833 const FeatureInfo::Workarounds& workarounds() const {
1834 return feature_info_->workarounds();
1837 bool ShouldDeferDraws() {
1838 return !offscreen_target_frame_buffer_.get() &&
1839 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1840 surface_->DeferDraws();
1843 bool ShouldDeferReads() {
1844 return !offscreen_target_frame_buffer_.get() &&
1845 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1846 surface_->DeferDraws();
1849 bool IsRobustnessSupported() {
1850 return has_robustness_extension_ &&
1851 context_->WasAllocatedUsingRobustnessExtension();
1854 error::Error WillAccessBoundFramebufferForDraw() {
1855 if (ShouldDeferDraws())
1856 return error::kDeferCommandUntilLater;
1857 if (!offscreen_target_frame_buffer_.get() &&
1858 !framebuffer_state_.bound_draw_framebuffer.get() &&
1859 !surface_->SetBackbufferAllocation(true))
1860 return error::kLostContext;
1861 return error::kNoError;
1864 error::Error WillAccessBoundFramebufferForRead() {
1865 if (ShouldDeferReads())
1866 return error::kDeferCommandUntilLater;
1867 if (!offscreen_target_frame_buffer_.get() &&
1868 !framebuffer_state_.bound_read_framebuffer.get() &&
1869 !surface_->SetBackbufferAllocation(true))
1870 return error::kLostContext;
1871 return error::kNoError;
1874 bool BackBufferHasAlpha() const {
1875 if (back_buffer_draw_buffer_ == GL_NONE)
1876 return false;
1877 if (offscreen_target_frame_buffer_.get()) {
1878 return (offscreen_target_color_format_ == GL_RGBA ||
1879 offscreen_target_color_format_ == GL_RGBA8);
1881 return (back_buffer_color_format_ == GL_RGBA ||
1882 back_buffer_color_format_ == GL_RGBA8);
1885 // Set remaining commands to process to 0 to force DoCommands to return
1886 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1887 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1889 void ProcessPendingReadPixels(bool did_finish);
1890 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1892 // Generate a member function prototype for each command in an automated and
1893 // typesafe way.
1894 #define GLES2_CMD_OP(name) \
1895 Error Handle##name(uint32 immediate_data_size, const void* data);
1897 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1899 #undef GLES2_CMD_OP
1901 // The GL context this decoder renders to on behalf of the client.
1902 scoped_refptr<gfx::GLSurface> surface_;
1903 scoped_refptr<gfx::GLContext> context_;
1905 // The ContextGroup for this decoder uses to track resources.
1906 scoped_refptr<ContextGroup> group_;
1908 DebugMarkerManager debug_marker_manager_;
1909 Logger logger_;
1911 // All the state for this context.
1912 ContextState state_;
1914 // Current width and height of the offscreen frame buffer.
1915 gfx::Size offscreen_size_;
1917 // Util to help with GL.
1918 GLES2Util util_;
1920 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1921 GLuint attrib_0_buffer_id_;
1923 // The value currently in attrib_0.
1924 Vec4 attrib_0_value_;
1926 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1927 bool attrib_0_buffer_matches_value_;
1929 // The size of attrib 0.
1930 GLsizei attrib_0_size_;
1932 // The buffer used to simulate GL_FIXED attribs.
1933 GLuint fixed_attrib_buffer_id_;
1935 // The size of fiixed attrib buffer.
1936 GLsizei fixed_attrib_buffer_size_;
1938 // The offscreen frame buffer that the client renders to. With EGL, the
1939 // depth and stencil buffers are separate. With regular GL there is a single
1940 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1941 // offscreen_target_stencil_render_buffer_ is unused.
1942 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1943 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1944 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1945 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1946 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1947 GLenum offscreen_target_color_format_;
1948 GLenum offscreen_target_depth_format_;
1949 GLenum offscreen_target_stencil_format_;
1950 GLsizei offscreen_target_samples_;
1951 GLboolean offscreen_target_buffer_preserved_;
1953 // The copy that is saved when SwapBuffers is called.
1954 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1955 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1956 scoped_refptr<TextureRef>
1957 offscreen_saved_color_texture_info_;
1959 // The copy that is used as the destination for multi-sample resolves.
1960 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1961 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1962 GLenum offscreen_saved_color_format_;
1964 scoped_ptr<QueryManager> query_manager_;
1966 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1968 scoped_ptr<ImageManager> image_manager_;
1970 base::Callback<void(gfx::Size, float)> resize_callback_;
1972 WaitSyncPointCallback wait_sync_point_callback_;
1974 ShaderCacheCallback shader_cache_callback_;
1976 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1978 // The format of the back buffer_
1979 GLenum back_buffer_color_format_;
1980 bool back_buffer_has_depth_;
1981 bool back_buffer_has_stencil_;
1983 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
1984 // or offscreen.
1985 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1986 // setting is set correctly when SwapBuffers().
1987 GLenum back_buffer_read_buffer_;
1988 GLenum back_buffer_draw_buffer_;
1990 bool surfaceless_;
1992 // Backbuffer attachments that are currently undefined.
1993 uint32 backbuffer_needs_clear_bits_;
1995 // The current decoder error communicates the decoder error through command
1996 // processing functions that do not return the error value. Should be set only
1997 // if not returning an error.
1998 error::Error current_decoder_error_;
2000 bool use_shader_translator_;
2001 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
2002 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
2004 DisallowedFeatures disallowed_features_;
2006 // Cached from ContextGroup
2007 const Validators* validators_;
2008 scoped_refptr<FeatureInfo> feature_info_;
2010 int frame_number_;
2012 // Number of commands remaining to be processed in DoCommands().
2013 int commands_to_process_;
2015 bool has_robustness_extension_;
2016 error::ContextLostReason context_lost_reason_;
2017 bool context_was_lost_;
2018 bool reset_by_robustness_extension_;
2019 bool supports_post_sub_buffer_;
2021 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2022 // 0: other types
2023 // 1: WebGL 1
2024 // 2: WebGL 2
2025 unsigned webgl_version_;
2027 // These flags are used to override the state of the shared feature_info_
2028 // member. Because the same FeatureInfo instance may be shared among many
2029 // contexts, the assumptions on the availablity of extensions in WebGL
2030 // contexts may be broken. These flags override the shared state to preserve
2031 // WebGL semantics.
2032 bool derivatives_explicitly_enabled_;
2033 bool frag_depth_explicitly_enabled_;
2034 bool draw_buffers_explicitly_enabled_;
2035 bool shader_texture_lod_explicitly_enabled_;
2037 bool compile_shader_always_succeeds_;
2039 // An optional behaviour to lose the context and group when OOM.
2040 bool lose_context_when_out_of_memory_;
2042 // Log extra info.
2043 bool service_logging_;
2045 #if defined(OS_MACOSX)
2046 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2047 TextureToIOSurfaceMap texture_to_io_surface_map_;
2048 #endif
2050 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2051 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2053 // Cached values of the currently assigned viewport dimensions.
2054 GLsizei viewport_max_width_;
2055 GLsizei viewport_max_height_;
2057 // Command buffer stats.
2058 base::TimeDelta total_processing_commands_time_;
2060 // States related to each manager.
2061 DecoderTextureState texture_state_;
2062 DecoderFramebufferState framebuffer_state_;
2064 scoped_ptr<GPUTracer> gpu_tracer_;
2065 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2066 const unsigned char* cb_command_trace_category_;
2067 const unsigned char* gpu_decoder_category_;
2068 int gpu_trace_level_;
2069 bool gpu_trace_commands_;
2070 bool gpu_debug_commands_;
2072 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2074 // Used to validate multisample renderbuffers if needed
2075 GLuint validation_texture_;
2076 GLuint validation_fbo_multisample_;
2077 GLuint validation_fbo_;
2079 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2080 uint32 immediate_data_size,
2081 const void* data);
2083 // A struct to hold info about each command.
2084 struct CommandInfo {
2085 CmdHandler cmd_handler;
2086 uint8 arg_flags; // How to handle the arguments for this command
2087 uint8 cmd_flags; // How to handle this command
2088 uint16 arg_count; // How many arguments are expected for this command.
2091 // A table of CommandInfo for all the commands.
2092 static const CommandInfo command_info[kNumCommands - kStartPoint];
2094 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2097 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2098 #define GLES2_CMD_OP(name) \
2100 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2101 cmds::name::cmd_flags, \
2102 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2104 , /* NOLINT */
2105 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2106 #undef GLES2_CMD_OP
2109 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2110 const char* function_name, ErrorState* error_state)
2111 : function_name_(function_name),
2112 error_state_(error_state) {
2113 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2116 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2117 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2120 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2121 TextureUnit& info = state->texture_units[0];
2122 GLuint last_id;
2123 scoped_refptr<TextureRef> texture_ref;
2124 switch (target) {
2125 case GL_TEXTURE_2D:
2126 texture_ref = info.bound_texture_2d;
2127 break;
2128 case GL_TEXTURE_CUBE_MAP:
2129 texture_ref = info.bound_texture_cube_map;
2130 break;
2131 case GL_TEXTURE_EXTERNAL_OES:
2132 texture_ref = info.bound_texture_external_oes;
2133 break;
2134 case GL_TEXTURE_RECTANGLE_ARB:
2135 texture_ref = info.bound_texture_rectangle_arb;
2136 break;
2137 default:
2138 NOTREACHED();
2139 break;
2141 if (texture_ref.get()) {
2142 last_id = texture_ref->service_id();
2143 } else {
2144 last_id = 0;
2147 glBindTexture(target, last_id);
2148 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2151 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2152 GLuint id,
2153 GLenum target)
2154 : state_(state),
2155 target_(target) {
2156 ScopedGLErrorSuppressor suppressor(
2157 "ScopedTextureBinder::ctor", state_->GetErrorState());
2159 // TODO(apatrick): Check if there are any other states that need to be reset
2160 // before binding a new texture.
2161 glActiveTexture(GL_TEXTURE0);
2162 glBindTexture(target, id);
2165 ScopedTextureBinder::~ScopedTextureBinder() {
2166 ScopedGLErrorSuppressor suppressor(
2167 "ScopedTextureBinder::dtor", state_->GetErrorState());
2168 RestoreCurrentTextureBindings(state_, target_);
2171 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2172 GLuint id)
2173 : state_(state) {
2174 ScopedGLErrorSuppressor suppressor(
2175 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2176 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2179 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2180 ScopedGLErrorSuppressor suppressor(
2181 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2182 state_->RestoreRenderbufferBindings();
2185 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2186 GLuint id)
2187 : decoder_(decoder) {
2188 ScopedGLErrorSuppressor suppressor(
2189 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2190 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2191 decoder->OnFboChanged();
2194 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2195 ScopedGLErrorSuppressor suppressor(
2196 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2197 decoder_->RestoreCurrentFramebufferBindings();
2200 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2201 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2202 : decoder_(decoder) {
2203 resolve_and_bind_ = (
2204 decoder_->offscreen_target_frame_buffer_.get() &&
2205 decoder_->IsOffscreenBufferMultisampled() &&
2206 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2207 enforce_internal_framebuffer));
2208 if (!resolve_and_bind_)
2209 return;
2211 ScopedGLErrorSuppressor suppressor(
2212 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2213 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2214 decoder_->offscreen_target_frame_buffer_->id());
2215 GLuint targetid;
2216 if (internal) {
2217 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2218 decoder_->offscreen_resolved_frame_buffer_.reset(
2219 new BackFramebuffer(decoder_));
2220 decoder_->offscreen_resolved_frame_buffer_->Create();
2221 decoder_->offscreen_resolved_color_texture_.reset(
2222 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2223 decoder_->offscreen_resolved_color_texture_->Create();
2225 DCHECK(decoder_->offscreen_saved_color_format_);
2226 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2227 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2228 false);
2229 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2230 decoder_->offscreen_resolved_color_texture_.get());
2231 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2232 GL_FRAMEBUFFER_COMPLETE) {
2233 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2234 << "because offscreen resolved FBO was incomplete.";
2235 return;
2238 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2239 } else {
2240 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2242 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2243 const int width = decoder_->offscreen_size_.width();
2244 const int height = decoder_->offscreen_size_.height();
2245 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2246 decoder->BlitFramebufferHelper(0,
2248 width,
2249 height,
2252 width,
2253 height,
2254 GL_COLOR_BUFFER_BIT,
2255 GL_NEAREST);
2256 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2259 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2260 if (!resolve_and_bind_)
2261 return;
2263 ScopedGLErrorSuppressor suppressor(
2264 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2265 decoder_->RestoreCurrentFramebufferBindings();
2266 if (decoder_->state_.enable_flags.scissor_test) {
2267 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2271 BackTexture::BackTexture(
2272 MemoryTracker* memory_tracker,
2273 ContextState* state)
2274 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2275 state_(state),
2276 bytes_allocated_(0),
2277 id_(0) {
2280 BackTexture::~BackTexture() {
2281 // This does not destroy the render texture because that would require that
2282 // the associated GL context was current. Just check that it was explicitly
2283 // destroyed.
2284 DCHECK_EQ(id_, 0u);
2287 void BackTexture::Create() {
2288 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2289 state_->GetErrorState());
2290 Destroy();
2291 glGenTextures(1, &id_);
2292 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2298 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2299 // never called on an offscreen context, no data will ever be uploaded to the
2300 // saved offscreen color texture (it is deferred until to when SwapBuffers
2301 // is called). My idea is that some nvidia drivers might have a bug where
2302 // deleting a texture that has never been populated might cause a
2303 // crash.
2304 glTexImage2D(
2305 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2307 bytes_allocated_ = 16u * 16u * 4u;
2308 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2311 bool BackTexture::AllocateStorage(
2312 const gfx::Size& size, GLenum format, bool zero) {
2313 DCHECK_NE(id_, 0u);
2314 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2315 state_->GetErrorState());
2316 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2317 uint32 image_size = 0;
2318 GLES2Util::ComputeImageDataSizes(
2319 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2320 NULL, NULL);
2322 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2323 return false;
2326 scoped_ptr<char[]> zero_data;
2327 if (zero) {
2328 zero_data.reset(new char[image_size]);
2329 memset(zero_data.get(), 0, image_size);
2332 glTexImage2D(GL_TEXTURE_2D,
2333 0, // mip level
2334 format,
2335 size.width(),
2336 size.height(),
2337 0, // border
2338 format,
2339 GL_UNSIGNED_BYTE,
2340 zero_data.get());
2342 size_ = size;
2344 bool success = glGetError() == GL_NO_ERROR;
2345 if (success) {
2346 memory_tracker_.TrackMemFree(bytes_allocated_);
2347 bytes_allocated_ = image_size;
2348 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2350 return success;
2353 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2354 DCHECK_NE(id_, 0u);
2355 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2356 state_->GetErrorState());
2357 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2358 glCopyTexImage2D(GL_TEXTURE_2D,
2359 0, // level
2360 format,
2361 0, 0,
2362 size.width(),
2363 size.height(),
2364 0); // border
2367 void BackTexture::Destroy() {
2368 if (id_ != 0) {
2369 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2370 state_->GetErrorState());
2371 glDeleteTextures(1, &id_);
2372 id_ = 0;
2374 memory_tracker_.TrackMemFree(bytes_allocated_);
2375 bytes_allocated_ = 0;
2378 void BackTexture::Invalidate() {
2379 id_ = 0;
2382 BackRenderbuffer::BackRenderbuffer(
2383 RenderbufferManager* renderbuffer_manager,
2384 MemoryTracker* memory_tracker,
2385 ContextState* state)
2386 : renderbuffer_manager_(renderbuffer_manager),
2387 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2388 state_(state),
2389 bytes_allocated_(0),
2390 id_(0) {
2393 BackRenderbuffer::~BackRenderbuffer() {
2394 // This does not destroy the render buffer because that would require that
2395 // the associated GL context was current. Just check that it was explicitly
2396 // destroyed.
2397 DCHECK_EQ(id_, 0u);
2400 void BackRenderbuffer::Create() {
2401 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2402 state_->GetErrorState());
2403 Destroy();
2404 glGenRenderbuffersEXT(1, &id_);
2407 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2408 const gfx::Size& size,
2409 GLenum format,
2410 GLsizei samples) {
2411 ScopedGLErrorSuppressor suppressor(
2412 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2413 ScopedRenderBufferBinder binder(state_, id_);
2415 uint32 estimated_size = 0;
2416 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2417 size.width(), size.height(), samples, format, &estimated_size)) {
2418 return false;
2421 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2422 return false;
2425 if (samples <= 1) {
2426 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2427 format,
2428 size.width(),
2429 size.height());
2430 } else {
2431 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2432 GL_RENDERBUFFER,
2433 samples,
2434 format,
2435 size.width(),
2436 size.height());
2438 bool success = glGetError() == GL_NO_ERROR;
2439 if (success) {
2440 // Mark the previously allocated bytes as free.
2441 memory_tracker_.TrackMemFree(bytes_allocated_);
2442 bytes_allocated_ = estimated_size;
2443 // Track the newly allocated bytes.
2444 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2446 return success;
2449 void BackRenderbuffer::Destroy() {
2450 if (id_ != 0) {
2451 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2452 state_->GetErrorState());
2453 glDeleteRenderbuffersEXT(1, &id_);
2454 id_ = 0;
2456 memory_tracker_.TrackMemFree(bytes_allocated_);
2457 bytes_allocated_ = 0;
2460 void BackRenderbuffer::Invalidate() {
2461 id_ = 0;
2464 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2465 : decoder_(decoder),
2466 id_(0) {
2469 BackFramebuffer::~BackFramebuffer() {
2470 // This does not destroy the frame buffer because that would require that
2471 // the associated GL context was current. Just check that it was explicitly
2472 // destroyed.
2473 DCHECK_EQ(id_, 0u);
2476 void BackFramebuffer::Create() {
2477 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2478 decoder_->GetErrorState());
2479 Destroy();
2480 glGenFramebuffersEXT(1, &id_);
2483 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2484 DCHECK_NE(id_, 0u);
2485 ScopedGLErrorSuppressor suppressor(
2486 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2487 ScopedFrameBufferBinder binder(decoder_, id_);
2488 GLuint attach_id = texture ? texture->id() : 0;
2489 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2490 GL_COLOR_ATTACHMENT0,
2491 GL_TEXTURE_2D,
2492 attach_id,
2496 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2497 BackRenderbuffer* render_buffer) {
2498 DCHECK_NE(id_, 0u);
2499 ScopedGLErrorSuppressor suppressor(
2500 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2501 ScopedFrameBufferBinder binder(decoder_, id_);
2502 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2503 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2504 target,
2505 GL_RENDERBUFFER,
2506 attach_id);
2509 void BackFramebuffer::Destroy() {
2510 if (id_ != 0) {
2511 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2512 decoder_->GetErrorState());
2513 glDeleteFramebuffersEXT(1, &id_);
2514 id_ = 0;
2518 void BackFramebuffer::Invalidate() {
2519 id_ = 0;
2522 GLenum BackFramebuffer::CheckStatus() {
2523 DCHECK_NE(id_, 0u);
2524 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2525 decoder_->GetErrorState());
2526 ScopedFrameBufferBinder binder(decoder_, id_);
2527 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2530 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2531 return new GLES2DecoderImpl(group);
2534 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2535 : GLES2Decoder(),
2536 group_(group),
2537 logger_(&debug_marker_manager_),
2538 state_(group_->feature_info(), this, &logger_),
2539 attrib_0_buffer_id_(0),
2540 attrib_0_buffer_matches_value_(true),
2541 attrib_0_size_(0),
2542 fixed_attrib_buffer_id_(0),
2543 fixed_attrib_buffer_size_(0),
2544 offscreen_target_color_format_(0),
2545 offscreen_target_depth_format_(0),
2546 offscreen_target_stencil_format_(0),
2547 offscreen_target_samples_(0),
2548 offscreen_target_buffer_preserved_(true),
2549 offscreen_saved_color_format_(0),
2550 back_buffer_color_format_(0),
2551 back_buffer_has_depth_(false),
2552 back_buffer_has_stencil_(false),
2553 back_buffer_read_buffer_(GL_BACK),
2554 back_buffer_draw_buffer_(GL_BACK),
2555 surfaceless_(false),
2556 backbuffer_needs_clear_bits_(0),
2557 current_decoder_error_(error::kNoError),
2558 use_shader_translator_(true),
2559 validators_(group_->feature_info()->validators()),
2560 feature_info_(group_->feature_info()),
2561 frame_number_(0),
2562 has_robustness_extension_(false),
2563 context_lost_reason_(error::kUnknown),
2564 context_was_lost_(false),
2565 reset_by_robustness_extension_(false),
2566 supports_post_sub_buffer_(false),
2567 webgl_version_(0),
2568 derivatives_explicitly_enabled_(false),
2569 frag_depth_explicitly_enabled_(false),
2570 draw_buffers_explicitly_enabled_(false),
2571 shader_texture_lod_explicitly_enabled_(false),
2572 compile_shader_always_succeeds_(false),
2573 lose_context_when_out_of_memory_(false),
2574 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2575 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2576 switches::kEnableGPUServiceLoggingGPU)
2577 : false),
2578 viewport_max_width_(0),
2579 viewport_max_height_(0),
2580 texture_state_(group_->feature_info()->workarounds()),
2581 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2582 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2583 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2584 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2585 gpu_trace_level_(2),
2586 gpu_trace_commands_(false),
2587 gpu_debug_commands_(false),
2588 validation_texture_(0),
2589 validation_fbo_multisample_(0),
2590 validation_fbo_(0) {
2591 DCHECK(group);
2593 // The shader translator is used for WebGL even when running on EGL
2594 // because additional restrictions are needed (like only enabling
2595 // GL_OES_standard_derivatives on demand). It is used for the unit
2596 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2597 // the empty string to CompileShader and this is not a valid shader.
2598 bool disable_translator =
2599 base::CommandLine::InitializedForCurrentProcess()
2600 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2601 switches::kDisableGLSLTranslator)
2602 : false;
2603 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2604 disable_translator) {
2605 use_shader_translator_ = false;
2609 GLES2DecoderImpl::~GLES2DecoderImpl() {
2612 bool GLES2DecoderImpl::Initialize(
2613 const scoped_refptr<gfx::GLSurface>& surface,
2614 const scoped_refptr<gfx::GLContext>& context,
2615 bool offscreen,
2616 const gfx::Size& offscreen_size,
2617 const DisallowedFeatures& disallowed_features,
2618 const std::vector<int32>& attribs) {
2619 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2620 DCHECK(context->IsCurrent(surface.get()));
2621 DCHECK(!context_.get());
2622 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2624 ContextCreationAttribHelper attrib_parser;
2625 if (!attrib_parser.Parse(attribs))
2626 return false;
2627 webgl_version_ = attrib_parser.webgl_version;
2629 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2631 set_initialized();
2632 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2634 if (base::CommandLine::InitializedForCurrentProcess()) {
2635 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2636 switches::kEnableGPUDebugging)) {
2637 set_debug(true);
2640 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2641 switches::kEnableGPUCommandLogging)) {
2642 set_log_commands(true);
2645 compile_shader_always_succeeds_ =
2646 base::CommandLine::ForCurrentProcess()->HasSwitch(
2647 switches::kCompileShaderAlwaysSucceeds);
2650 // Take ownership of the context and surface. The surface can be replaced with
2651 // SetSurface.
2652 context_ = context;
2653 surface_ = surface;
2655 // Create GPU Tracer for timing values.
2656 gpu_tracer_.reset(new GPUTracer(this));
2658 if (feature_info_->workarounds().disable_timestamp_queries) {
2659 // Forcing time elapsed query for any GPU Timing Client forces it for all
2660 // clients in the context.
2661 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2664 // Save the loseContextWhenOutOfMemory context creation attribute.
2665 lose_context_when_out_of_memory_ =
2666 attrib_parser.lose_context_when_out_of_memory;
2668 // If the failIfMajorPerformanceCaveat context creation attribute was true
2669 // and we are using a software renderer, fail.
2670 if (attrib_parser.fail_if_major_perf_caveat &&
2671 feature_info_->feature_flags().is_swiftshader) {
2672 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2673 Destroy(true);
2674 return false;
2677 disallowed_features_ = disallowed_features;
2678 if (webgl_version_ == 1) {
2679 disallowed_features_.npot_support = true;
2682 if (!group_->Initialize(this,
2683 ContextGroup::GetContextType(webgl_version_),
2684 disallowed_features_)) {
2685 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2686 Destroy(true);
2687 return false;
2689 CHECK_GL_ERROR();
2691 if (webgl_version_ == 2) {
2692 if (!feature_info_->IsES3Capable()) {
2693 LOG(ERROR) << "Underlying driver does not support ES3.";
2694 Destroy(true);
2695 return false;
2697 feature_info_->EnableES3Validators();
2698 set_unsafe_es3_apis_enabled(true);
2701 state_.attrib_values.resize(group_->max_vertex_attribs());
2702 vertex_array_manager_.reset(new VertexArrayManager());
2704 GLuint default_vertex_attrib_service_id = 0;
2705 if (features().native_vertex_array_object) {
2706 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2707 glBindVertexArrayOES(default_vertex_attrib_service_id);
2710 state_.default_vertex_attrib_manager =
2711 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2713 state_.default_vertex_attrib_manager->Initialize(
2714 group_->max_vertex_attribs(),
2715 feature_info_->workarounds().init_vertex_attributes);
2717 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2718 DoBindVertexArrayOES(0);
2720 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2722 image_manager_.reset(new ImageManager);
2724 util_.set_num_compressed_texture_formats(
2725 validators_->compressed_texture_format.GetValues().size());
2727 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2728 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2729 // OpenGL ES 2.0 does not have this issue.
2730 glEnableVertexAttribArray(0);
2732 glGenBuffersARB(1, &attrib_0_buffer_id_);
2733 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2734 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2735 glBindBuffer(GL_ARRAY_BUFFER, 0);
2736 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2738 state_.texture_units.resize(group_->max_texture_units());
2739 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2740 glActiveTexture(GL_TEXTURE0 + tt);
2741 // We want the last bind to be 2D.
2742 TextureRef* ref;
2743 if (features().oes_egl_image_external) {
2744 ref = texture_manager()->GetDefaultTextureInfo(
2745 GL_TEXTURE_EXTERNAL_OES);
2746 state_.texture_units[tt].bound_texture_external_oes = ref;
2747 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2749 if (features().arb_texture_rectangle) {
2750 ref = texture_manager()->GetDefaultTextureInfo(
2751 GL_TEXTURE_RECTANGLE_ARB);
2752 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2753 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2755 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2756 state_.texture_units[tt].bound_texture_cube_map = ref;
2757 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2758 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2759 state_.texture_units[tt].bound_texture_2d = ref;
2760 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2762 glActiveTexture(GL_TEXTURE0);
2763 CHECK_GL_ERROR();
2765 // cache ALPHA_BITS result for re-use with clear behaviour
2766 GLint alpha_bits = 0;
2768 if (offscreen) {
2769 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2770 features().chromium_framebuffer_multisample) {
2771 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2772 // max_sample_count must be initialized to a sane value. If
2773 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2774 GLint max_sample_count = 1;
2775 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2776 offscreen_target_samples_ = std::min(attrib_parser.samples,
2777 max_sample_count);
2778 } else {
2779 offscreen_target_samples_ = 1;
2781 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2783 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2784 const bool rgb8_supported =
2785 context_->HasExtension("GL_OES_rgb8_rgba8");
2786 // The only available default render buffer formats in GLES2 have very
2787 // little precision. Don't enable multisampling unless 8-bit render
2788 // buffer formats are available--instead fall back to 8-bit textures.
2789 if (rgb8_supported && offscreen_target_samples_ > 1) {
2790 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2791 GL_RGBA8 : GL_RGB8;
2792 } else {
2793 offscreen_target_samples_ = 1;
2794 offscreen_target_color_format_ =
2795 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2796 ? GL_RGBA
2797 : GL_RGB;
2800 // ANGLE only supports packed depth/stencil formats, so use it if it is
2801 // available.
2802 const bool depth24_stencil8_supported =
2803 feature_info_->feature_flags().packed_depth24_stencil8;
2804 VLOG(1) << "GL_OES_packed_depth_stencil "
2805 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2806 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2807 depth24_stencil8_supported) {
2808 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2809 offscreen_target_stencil_format_ = 0;
2810 } else {
2811 // It may be the case that this depth/stencil combination is not
2812 // supported, but this will be checked later by CheckFramebufferStatus.
2813 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2814 GL_DEPTH_COMPONENT16 : 0;
2815 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2816 GL_STENCIL_INDEX8 : 0;
2818 } else {
2819 offscreen_target_color_format_ =
2820 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2821 ? GL_RGBA
2822 : GL_RGB;
2824 // If depth is requested at all, use the packed depth stencil format if
2825 // it's available, as some desktop GL drivers don't support any non-packed
2826 // formats for depth attachments.
2827 const bool depth24_stencil8_supported =
2828 feature_info_->feature_flags().packed_depth24_stencil8;
2829 VLOG(1) << "GL_EXT_packed_depth_stencil "
2830 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2832 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2833 depth24_stencil8_supported) {
2834 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2835 offscreen_target_stencil_format_ = 0;
2836 } else {
2837 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2838 GL_DEPTH_COMPONENT : 0;
2839 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2840 GL_STENCIL_INDEX : 0;
2844 offscreen_saved_color_format_ =
2845 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2846 ? GL_RGBA
2847 : GL_RGB;
2849 // Create the target frame buffer. This is the one that the client renders
2850 // directly to.
2851 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2852 offscreen_target_frame_buffer_->Create();
2853 // Due to GLES2 format limitations, either the color texture (for
2854 // non-multisampling) or the color render buffer (for multisampling) will be
2855 // attached to the offscreen frame buffer. The render buffer has more
2856 // limited formats available to it, but the texture can't do multisampling.
2857 if (IsOffscreenBufferMultisampled()) {
2858 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2859 renderbuffer_manager(), memory_tracker(), &state_));
2860 offscreen_target_color_render_buffer_->Create();
2861 } else {
2862 offscreen_target_color_texture_.reset(new BackTexture(
2863 memory_tracker(), &state_));
2864 offscreen_target_color_texture_->Create();
2866 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2867 renderbuffer_manager(), memory_tracker(), &state_));
2868 offscreen_target_depth_render_buffer_->Create();
2869 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2870 renderbuffer_manager(), memory_tracker(), &state_));
2871 offscreen_target_stencil_render_buffer_->Create();
2873 // Create the saved offscreen texture. The target frame buffer is copied
2874 // here when SwapBuffers is called.
2875 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2876 offscreen_saved_frame_buffer_->Create();
2878 offscreen_saved_color_texture_.reset(new BackTexture(
2879 memory_tracker(), &state_));
2880 offscreen_saved_color_texture_->Create();
2882 // Allocate the render buffers at their initial size and check the status
2883 // of the frame buffers is okay.
2884 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2885 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2886 Destroy(true);
2887 return false;
2890 state_.viewport_width = offscreen_size.width();
2891 state_.viewport_height = offscreen_size.height();
2893 // Allocate the offscreen saved color texture.
2894 DCHECK(offscreen_saved_color_format_);
2895 offscreen_saved_color_texture_->AllocateStorage(
2896 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2898 offscreen_saved_frame_buffer_->AttachRenderTexture(
2899 offscreen_saved_color_texture_.get());
2900 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2901 GL_FRAMEBUFFER_COMPLETE) {
2902 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2903 Destroy(true);
2904 return false;
2907 // Bind to the new default frame buffer (the offscreen target frame buffer).
2908 // This should now be associated with ID zero.
2909 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2910 } else {
2911 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2912 // These are NOT if the back buffer has these proprorties. They are
2913 // if we want the command buffer to enforce them regardless of what
2914 // the real backbuffer is assuming the real back buffer gives us more than
2915 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2916 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2917 // can't do anything about that.
2919 if (!surfaceless_) {
2920 GLint depth_bits = 0;
2921 GLint stencil_bits = 0;
2923 bool default_fb = (GetBackbufferServiceId() == 0);
2925 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2926 glGetFramebufferAttachmentParameterivEXT(
2927 GL_FRAMEBUFFER,
2928 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2929 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2930 glGetFramebufferAttachmentParameterivEXT(
2931 GL_FRAMEBUFFER,
2932 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2933 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2934 glGetFramebufferAttachmentParameterivEXT(
2935 GL_FRAMEBUFFER,
2936 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2937 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2938 } else {
2939 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2940 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2941 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2944 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2945 // the user requested RGB then RGB. If the user did not specify a
2946 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2947 back_buffer_color_format_ =
2948 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2949 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2950 back_buffer_has_stencil_ =
2951 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2954 state_.viewport_width = surface->GetSize().width();
2955 state_.viewport_height = surface->GetSize().height();
2958 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2959 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2960 // isn't well documented; it was discovered in the Khronos OpenGL ES
2961 // mailing list archives. It also implicitly enables the desktop GL
2962 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2963 // variable in fragment shaders.
2964 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2965 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2966 glEnable(GL_POINT_SPRITE);
2969 has_robustness_extension_ =
2970 context->HasExtension("GL_ARB_robustness") ||
2971 context->HasExtension("GL_KHR_robustness") ||
2972 context->HasExtension("GL_EXT_robustness");
2974 if (!InitializeShaderTranslator()) {
2975 return false;
2978 GLint viewport_params[4] = { 0 };
2979 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2980 viewport_max_width_ = viewport_params[0];
2981 viewport_max_height_ = viewport_params[1];
2983 state_.scissor_width = state_.viewport_width;
2984 state_.scissor_height = state_.viewport_height;
2986 // Set all the default state because some GL drivers get it wrong.
2987 state_.InitCapabilities(NULL);
2988 state_.InitState(NULL);
2989 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2991 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2992 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2993 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2994 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2995 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2997 bool call_gl_clear = !surfaceless_;
2998 #if defined(OS_ANDROID)
2999 // Temporary workaround for Android WebView because this clear ignores the
3000 // clip and corrupts that external UI of the App. Not calling glClear is ok
3001 // because the system already clears the buffer before each draw. Proper
3002 // fix might be setting the scissor clip properly before initialize. See
3003 // crbug.com/259023 for details.
3004 call_gl_clear = surface_->GetHandle();
3005 #endif
3006 if (call_gl_clear) {
3007 // On configs where we report no alpha, if the underlying surface has
3008 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3009 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
3010 if (clear_alpha) {
3011 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3014 // Clear the backbuffer.
3015 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3017 // Restore alpha clear value if we changed it.
3018 if (clear_alpha) {
3019 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3023 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
3024 if (feature_info_->workarounds()
3025 .disable_post_sub_buffers_for_onscreen_surfaces &&
3026 !surface->IsOffscreen())
3027 supports_post_sub_buffer_ = false;
3029 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
3030 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
3033 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3034 context_->SetUnbindFboOnMakeCurrent();
3037 // Only compositor contexts are known to use only the subset of GL
3038 // that can be safely migrated between the iGPU and the dGPU. Mark
3039 // those contexts as safe to forcibly transition between the GPUs.
3040 // http://crbug.com/180876, http://crbug.com/227228
3041 if (!offscreen)
3042 context_->SetSafeToForceGpuSwitch();
3044 async_pixel_transfer_manager_.reset(
3045 AsyncPixelTransferManager::Create(context.get()));
3046 async_pixel_transfer_manager_->Initialize(texture_manager());
3048 if (workarounds().gl_clear_broken) {
3049 DCHECK(!clear_framebuffer_blit_.get());
3050 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3051 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3052 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3053 return false;
3056 framebuffer_manager()->AddObserver(this);
3058 return true;
3061 Capabilities GLES2DecoderImpl::GetCapabilities() {
3062 DCHECK(initialized());
3063 Capabilities caps;
3064 caps.VisitPrecisions([](GLenum shader, GLenum type,
3065 Capabilities::ShaderPrecision* shader_precision) {
3066 GLint range[2] = {0, 0};
3067 GLint precision = 0;
3068 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3069 shader_precision->min_range = range[0];
3070 shader_precision->max_range = range[1];
3071 shader_precision->precision = precision;
3073 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3074 &caps.max_combined_texture_image_units);
3075 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3076 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3077 &caps.max_fragment_uniform_vectors);
3078 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3079 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3080 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3081 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3082 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3083 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3084 &caps.max_vertex_texture_image_units);
3085 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3086 &caps.max_vertex_uniform_vectors);
3087 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3088 &caps.num_compressed_texture_formats);
3089 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3090 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3091 &caps.bind_generates_resource_chromium);
3092 if (unsafe_es3_apis_enabled()) {
3093 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3094 // but for now we clamp them to 32-bit max.
3095 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3096 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3097 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3098 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3099 &caps.max_combined_fragment_uniform_components);
3100 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3101 &caps.max_combined_uniform_blocks);
3102 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3103 &caps.max_combined_vertex_uniform_components);
3104 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3105 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3106 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3107 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3108 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3109 &caps.max_fragment_input_components);
3110 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3111 &caps.max_fragment_uniform_blocks);
3112 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3113 &caps.max_fragment_uniform_components);
3114 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3115 &caps.max_program_texel_offset);
3116 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3117 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3118 // returned.
3119 if (caps.max_server_wait_timeout < 0)
3120 caps.max_server_wait_timeout = 0;
3121 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3122 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3123 &caps.max_transform_feedback_interleaved_components);
3124 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3125 &caps.max_transform_feedback_separate_attribs);
3126 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3127 &caps.max_transform_feedback_separate_components);
3128 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3129 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3130 &caps.max_uniform_buffer_bindings);
3131 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3132 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3133 &caps.max_vertex_output_components);
3134 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3135 &caps.max_vertex_uniform_blocks);
3136 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3137 &caps.max_vertex_uniform_components);
3138 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3139 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3140 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3141 &caps.num_program_binary_formats);
3142 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3143 &caps.uniform_buffer_offset_alignment);
3144 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3145 caps.major_version = 3;
3146 caps.minor_version = 0;
3148 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3149 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3150 unsafe_es3_apis_enabled()) {
3151 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3154 caps.egl_image_external =
3155 feature_info_->feature_flags().oes_egl_image_external;
3156 caps.texture_format_atc =
3157 feature_info_->feature_flags().ext_texture_format_atc;
3158 caps.texture_format_bgra8888 =
3159 feature_info_->feature_flags().ext_texture_format_bgra8888;
3160 caps.texture_format_dxt1 =
3161 feature_info_->feature_flags().ext_texture_format_dxt1;
3162 caps.texture_format_dxt5 =
3163 feature_info_->feature_flags().ext_texture_format_dxt5;
3164 caps.texture_format_etc1 =
3165 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3166 caps.texture_format_etc1_npot =
3167 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3168 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3169 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3170 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3171 caps.discard_framebuffer =
3172 feature_info_->feature_flags().ext_discard_framebuffer;
3173 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3175 #if defined(OS_MACOSX)
3176 // This is unconditionally true on mac, no need to test for it at runtime.
3177 caps.iosurface = true;
3178 #endif
3180 caps.post_sub_buffer = supports_post_sub_buffer_;
3181 caps.image = true;
3182 caps.surfaceless = surfaceless_;
3184 caps.blend_equation_advanced =
3185 feature_info_->feature_flags().blend_equation_advanced;
3186 caps.blend_equation_advanced_coherent =
3187 feature_info_->feature_flags().blend_equation_advanced_coherent;
3188 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3189 caps.max_copy_texture_chromium_size =
3190 feature_info_->workarounds().max_copy_texture_chromium_size;
3191 caps.render_buffer_format_bgra8888 =
3192 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3193 caps.occlusion_query_boolean =
3194 feature_info_->feature_flags().occlusion_query_boolean;
3195 caps.timer_queries =
3196 query_manager_->GPUTimingAvailable();
3197 return caps;
3200 void GLES2DecoderImpl::UpdateCapabilities() {
3201 util_.set_num_compressed_texture_formats(
3202 validators_->compressed_texture_format.GetValues().size());
3203 util_.set_num_shader_binary_formats(
3204 validators_->shader_binary_format.GetValues().size());
3207 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3208 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3210 if (!use_shader_translator_) {
3211 return true;
3213 ShBuiltInResources resources;
3214 ShInitBuiltInResources(&resources);
3215 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3216 resources.MaxVertexUniformVectors =
3217 group_->max_vertex_uniform_vectors();
3218 resources.MaxVaryingVectors = group_->max_varying_vectors();
3219 resources.MaxVertexTextureImageUnits =
3220 group_->max_vertex_texture_image_units();
3221 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3222 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3223 resources.MaxFragmentUniformVectors =
3224 group_->max_fragment_uniform_vectors();
3225 resources.MaxDrawBuffers = group_->max_draw_buffers();
3226 resources.MaxExpressionComplexity = 256;
3227 resources.MaxCallStackDepth = 256;
3229 GLint range[2] = { 0, 0 };
3230 GLint precision = 0;
3231 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3232 range, &precision);
3233 resources.FragmentPrecisionHigh =
3234 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3236 if (IsWebGLContext()) {
3237 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3238 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3239 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3240 if (!draw_buffers_explicitly_enabled_)
3241 resources.MaxDrawBuffers = 1;
3242 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3243 resources.NV_draw_buffers =
3244 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3245 } else {
3246 resources.OES_standard_derivatives =
3247 features().oes_standard_derivatives ? 1 : 0;
3248 resources.ARB_texture_rectangle =
3249 features().arb_texture_rectangle ? 1 : 0;
3250 resources.OES_EGL_image_external =
3251 features().oes_egl_image_external ? 1 : 0;
3252 resources.EXT_draw_buffers =
3253 features().ext_draw_buffers ? 1 : 0;
3254 resources.EXT_frag_depth =
3255 features().ext_frag_depth ? 1 : 0;
3256 resources.EXT_shader_texture_lod =
3257 features().ext_shader_texture_lod ? 1 : 0;
3258 resources.NV_draw_buffers =
3259 features().nv_draw_buffers ? 1 : 0;
3262 ShShaderSpec shader_spec;
3263 if (IsWebGLContext()) {
3264 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3265 } else {
3266 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3269 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3270 features().enable_shader_name_hashing)
3271 resources.HashFunction = &CityHash64;
3272 else
3273 resources.HashFunction = NULL;
3275 int driver_bug_workarounds = 0;
3276 if (workarounds().needs_glsl_built_in_function_emulation)
3277 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3278 if (workarounds().init_gl_position_in_vertex_shader)
3279 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3280 if (workarounds().unfold_short_circuit_as_ternary_operation)
3281 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3282 if (workarounds().init_varyings_without_static_use)
3283 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3284 if (workarounds().unroll_for_loop_with_sampler_array_index)
3285 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3286 if (workarounds().scalarize_vec_and_mat_constructor_args)
3287 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3288 if (workarounds().regenerate_struct_names)
3289 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3290 if (workarounds().remove_pow_with_constant_exponent)
3291 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3293 if (base::CommandLine::InitializedForCurrentProcess() &&
3294 base::CommandLine::ForCurrentProcess()->HasSwitch(
3295 switches::kEmulateShaderPrecision))
3296 resources.WEBGL_debug_shader_precision = true;
3298 ShShaderOutput shader_output_language =
3299 ShaderTranslator::GetShaderOutputLanguageForContext(
3300 feature_info_->gl_version_info());
3302 vertex_translator_ = shader_translator_cache()->GetTranslator(
3303 GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
3304 static_cast<ShCompileOptions>(driver_bug_workarounds));
3305 if (!vertex_translator_.get()) {
3306 LOG(ERROR) << "Could not initialize vertex shader translator.";
3307 Destroy(true);
3308 return false;
3311 fragment_translator_ = shader_translator_cache()->GetTranslator(
3312 GL_FRAGMENT_SHADER, shader_spec, &resources, shader_output_language,
3313 static_cast<ShCompileOptions>(driver_bug_workarounds));
3314 if (!fragment_translator_.get()) {
3315 LOG(ERROR) << "Could not initialize fragment shader translator.";
3316 Destroy(true);
3317 return false;
3319 return true;
3322 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3323 for (GLsizei ii = 0; ii < n; ++ii) {
3324 if (GetBuffer(client_ids[ii])) {
3325 return false;
3328 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3329 glGenBuffersARB(n, service_ids.get());
3330 for (GLsizei ii = 0; ii < n; ++ii) {
3331 CreateBuffer(client_ids[ii], service_ids[ii]);
3333 return true;
3336 bool GLES2DecoderImpl::GenFramebuffersHelper(
3337 GLsizei n, const GLuint* client_ids) {
3338 for (GLsizei ii = 0; ii < n; ++ii) {
3339 if (GetFramebuffer(client_ids[ii])) {
3340 return false;
3343 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3344 glGenFramebuffersEXT(n, service_ids.get());
3345 for (GLsizei ii = 0; ii < n; ++ii) {
3346 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3348 return true;
3351 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3352 GLsizei n, const GLuint* client_ids) {
3353 for (GLsizei ii = 0; ii < n; ++ii) {
3354 if (GetRenderbuffer(client_ids[ii])) {
3355 return false;
3358 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3359 glGenRenderbuffersEXT(n, service_ids.get());
3360 for (GLsizei ii = 0; ii < n; ++ii) {
3361 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3363 return true;
3366 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3367 const GLuint* client_ids) {
3368 for (GLsizei ii = 0; ii < n; ++ii) {
3369 if (GetValuebuffer(client_ids[ii])) {
3370 return false;
3373 for (GLsizei ii = 0; ii < n; ++ii) {
3374 CreateValuebuffer(client_ids[ii]);
3376 return true;
3379 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3380 for (GLsizei ii = 0; ii < n; ++ii) {
3381 if (GetTexture(client_ids[ii])) {
3382 return false;
3385 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3386 glGenTextures(n, service_ids.get());
3387 for (GLsizei ii = 0; ii < n; ++ii) {
3388 CreateTexture(client_ids[ii], service_ids[ii]);
3390 return true;
3393 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3394 GLsizei range) {
3395 GLuint last_client_id;
3396 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3397 return false;
3399 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3400 return false;
3402 GLuint first_service_id = glGenPathsNV(range);
3403 if (first_service_id == 0) {
3404 // We have to fail the connection here, because client has already
3405 // succeeded in allocating the ids. This happens if we allocate
3406 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3407 // example).
3408 return false;
3410 // GenPathsNV does not wrap.
3411 DCHECK(first_service_id + range - 1 >= first_service_id);
3413 path_manager()->CreatePathRange(first_client_id, last_client_id,
3414 first_service_id);
3416 return true;
3419 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3420 GLsizei range) {
3421 GLuint last_client_id;
3422 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3423 return false;
3425 path_manager()->RemovePaths(first_client_id, last_client_id);
3426 return true;
3429 void GLES2DecoderImpl::DeleteBuffersHelper(
3430 GLsizei n, const GLuint* client_ids) {
3431 for (GLsizei ii = 0; ii < n; ++ii) {
3432 Buffer* buffer = GetBuffer(client_ids[ii]);
3433 if (buffer && !buffer->IsDeleted()) {
3434 buffer->RemoveMappedRange();
3435 state_.RemoveBoundBuffer(buffer);
3436 RemoveBuffer(client_ids[ii]);
3441 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3442 GLsizei n, const GLuint* client_ids) {
3443 bool supports_separate_framebuffer_binds =
3444 features().chromium_framebuffer_multisample;
3446 for (GLsizei ii = 0; ii < n; ++ii) {
3447 Framebuffer* framebuffer =
3448 GetFramebuffer(client_ids[ii]);
3449 if (framebuffer && !framebuffer->IsDeleted()) {
3450 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3451 GLenum target = supports_separate_framebuffer_binds ?
3452 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3454 // Unbind attachments on FBO before deletion.
3455 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3456 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3458 glBindFramebufferEXT(target, GetBackbufferServiceId());
3459 framebuffer_state_.bound_draw_framebuffer = NULL;
3460 framebuffer_state_.clear_state_dirty = true;
3462 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3463 framebuffer_state_.bound_read_framebuffer = NULL;
3464 GLenum target = supports_separate_framebuffer_binds ?
3465 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3466 glBindFramebufferEXT(target, GetBackbufferServiceId());
3468 OnFboChanged();
3469 RemoveFramebuffer(client_ids[ii]);
3474 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3475 GLsizei n, const GLuint* client_ids) {
3476 bool supports_separate_framebuffer_binds =
3477 features().chromium_framebuffer_multisample;
3478 for (GLsizei ii = 0; ii < n; ++ii) {
3479 Renderbuffer* renderbuffer =
3480 GetRenderbuffer(client_ids[ii]);
3481 if (renderbuffer && !renderbuffer->IsDeleted()) {
3482 if (state_.bound_renderbuffer.get() == renderbuffer) {
3483 state_.bound_renderbuffer = NULL;
3485 // Unbind from current framebuffers.
3486 if (supports_separate_framebuffer_binds) {
3487 if (framebuffer_state_.bound_read_framebuffer.get()) {
3488 framebuffer_state_.bound_read_framebuffer
3489 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3491 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3492 framebuffer_state_.bound_draw_framebuffer
3493 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3495 } else {
3496 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3497 framebuffer_state_.bound_draw_framebuffer
3498 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3501 framebuffer_state_.clear_state_dirty = true;
3502 RemoveRenderbuffer(client_ids[ii]);
3507 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3508 GLsizei n,
3509 const GLuint* client_ids) {
3510 for (GLsizei ii = 0; ii < n; ++ii) {
3511 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3512 if (valuebuffer) {
3513 if (state_.bound_valuebuffer.get() == valuebuffer) {
3514 state_.bound_valuebuffer = NULL;
3516 RemoveValuebuffer(client_ids[ii]);
3521 void GLES2DecoderImpl::DeleteTexturesHelper(
3522 GLsizei n, const GLuint* client_ids) {
3523 bool supports_separate_framebuffer_binds =
3524 features().chromium_framebuffer_multisample;
3525 for (GLsizei ii = 0; ii < n; ++ii) {
3526 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3527 if (texture_ref) {
3528 Texture* texture = texture_ref->texture();
3529 if (texture->IsAttachedToFramebuffer()) {
3530 framebuffer_state_.clear_state_dirty = true;
3532 // Unbind texture_ref from texture_ref units.
3533 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3534 state_.texture_units[jj].Unbind(texture_ref);
3536 // Unbind from current framebuffers.
3537 if (supports_separate_framebuffer_binds) {
3538 if (framebuffer_state_.bound_read_framebuffer.get()) {
3539 framebuffer_state_.bound_read_framebuffer
3540 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3542 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3543 framebuffer_state_.bound_draw_framebuffer
3544 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3546 } else {
3547 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3548 framebuffer_state_.bound_draw_framebuffer
3549 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3552 #if defined(OS_MACOSX)
3553 GLuint service_id = texture->service_id();
3554 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3555 ReleaseIOSurfaceForTexture(service_id);
3557 #endif
3558 RemoveTexture(client_ids[ii]);
3563 // } // anonymous namespace
3565 bool GLES2DecoderImpl::MakeCurrent() {
3566 if (!context_.get())
3567 return false;
3569 if (WasContextLost()) {
3570 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3571 return false;
3574 if (!context_->MakeCurrent(surface_.get())) {
3575 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3576 MarkContextLost(error::kMakeCurrentFailed);
3577 group_->LoseContexts(error::kUnknown);
3578 return false;
3581 if (CheckResetStatus()) {
3582 LOG(ERROR)
3583 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3584 group_->LoseContexts(error::kUnknown);
3585 return false;
3588 ProcessFinishedAsyncTransfers();
3590 // Rebind the FBO if it was unbound by the context.
3591 if (workarounds().unbind_fbo_on_context_switch)
3592 RestoreFramebufferBindings();
3594 framebuffer_state_.clear_state_dirty = true;
3596 return true;
3599 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3600 ProcessPendingReadPixels(false);
3601 if (engine() && query_manager_.get())
3602 query_manager_->ProcessPendingTransferQueries();
3604 // TODO(epenner): Is there a better place to do this?
3605 // This needs to occur before we execute any batch of commands
3606 // from the client, as the client may have recieved an async
3607 // completion while issuing those commands.
3608 // "DidFlushStart" would be ideal if we had such a callback.
3609 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3612 static void RebindCurrentFramebuffer(
3613 GLenum target,
3614 Framebuffer* framebuffer,
3615 GLuint back_buffer_service_id) {
3616 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3618 if (framebuffer_id == 0) {
3619 framebuffer_id = back_buffer_service_id;
3622 glBindFramebufferEXT(target, framebuffer_id);
3625 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3626 framebuffer_state_.clear_state_dirty = true;
3628 if (!features().chromium_framebuffer_multisample) {
3629 RebindCurrentFramebuffer(
3630 GL_FRAMEBUFFER,
3631 framebuffer_state_.bound_draw_framebuffer.get(),
3632 GetBackbufferServiceId());
3633 } else {
3634 RebindCurrentFramebuffer(
3635 GL_READ_FRAMEBUFFER_EXT,
3636 framebuffer_state_.bound_read_framebuffer.get(),
3637 GetBackbufferServiceId());
3638 RebindCurrentFramebuffer(
3639 GL_DRAW_FRAMEBUFFER_EXT,
3640 framebuffer_state_.bound_draw_framebuffer.get(),
3641 GetBackbufferServiceId());
3643 OnFboChanged();
3646 bool GLES2DecoderImpl::CheckFramebufferValid(
3647 Framebuffer* framebuffer,
3648 GLenum target, const char* func_name) {
3649 if (!framebuffer) {
3650 if (surfaceless_)
3651 return false;
3652 if (backbuffer_needs_clear_bits_) {
3653 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3654 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3655 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3656 glClearStencil(0);
3657 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3658 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3659 glClearDepth(1.0f);
3660 state_.SetDeviceDepthMask(GL_TRUE);
3661 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3662 bool reset_draw_buffer = false;
3663 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3664 back_buffer_draw_buffer_ == GL_NONE) {
3665 reset_draw_buffer = true;
3666 GLenum buf = GL_BACK;
3667 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3668 buf = GL_COLOR_ATTACHMENT0;
3669 glDrawBuffersARB(1, &buf);
3671 glClear(backbuffer_needs_clear_bits_);
3672 if (reset_draw_buffer) {
3673 GLenum buf = GL_NONE;
3674 glDrawBuffersARB(1, &buf);
3676 backbuffer_needs_clear_bits_ = 0;
3677 RestoreClearState();
3679 return true;
3682 if (framebuffer_manager()->IsComplete(framebuffer)) {
3683 return true;
3686 GLenum completeness = framebuffer->IsPossiblyComplete();
3687 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3688 LOCAL_SET_GL_ERROR(
3689 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3690 return false;
3693 // Are all the attachments cleared?
3694 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3695 texture_manager()->HaveUnclearedMips()) {
3696 if (!framebuffer->IsCleared()) {
3697 // Can we clear them?
3698 if (framebuffer->GetStatus(texture_manager(), target) !=
3699 GL_FRAMEBUFFER_COMPLETE) {
3700 LOCAL_SET_GL_ERROR(
3701 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3702 "framebuffer incomplete (clear)");
3703 return false;
3705 ClearUnclearedAttachments(target, framebuffer);
3709 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3710 if (framebuffer->GetStatus(texture_manager(), target) !=
3711 GL_FRAMEBUFFER_COMPLETE) {
3712 LOCAL_SET_GL_ERROR(
3713 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3714 "framebuffer incomplete (check)");
3715 return false;
3717 framebuffer_manager()->MarkAsComplete(framebuffer);
3720 // NOTE: At this point we don't know if the framebuffer is complete but
3721 // we DO know that everything that needs to be cleared has been cleared.
3722 return true;
3725 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3726 if (!features().chromium_framebuffer_multisample) {
3727 bool valid = CheckFramebufferValid(
3728 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3729 func_name);
3731 if (valid)
3732 OnUseFramebuffer();
3734 return valid;
3736 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3737 GL_DRAW_FRAMEBUFFER_EXT,
3738 func_name) &&
3739 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3740 GL_READ_FRAMEBUFFER_EXT,
3741 func_name);
3744 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3745 const char* func_name) {
3746 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3747 framebuffer_state_.bound_read_framebuffer.get() :
3748 framebuffer_state_.bound_draw_framebuffer.get();
3749 if (!framebuffer)
3750 return true;
3751 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3752 LOCAL_SET_GL_ERROR(
3753 GL_INVALID_OPERATION, func_name, "no color image attached");
3754 return false;
3756 return true;
3759 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3760 TextureRef* texture, GLint level) {
3761 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3762 framebuffer_state_.bound_read_framebuffer.get() :
3763 framebuffer_state_.bound_draw_framebuffer.get();
3764 if (!framebuffer)
3765 return false;
3766 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3767 GL_COLOR_ATTACHMENT0);
3768 if (!attachment)
3769 return false;
3770 return attachment->FormsFeedbackLoop(texture, level);
3773 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3774 Framebuffer* framebuffer =
3775 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3776 if (framebuffer != NULL) {
3777 const Framebuffer::Attachment* attachment =
3778 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3779 if (attachment) {
3780 return gfx::Size(attachment->width(), attachment->height());
3782 return gfx::Size(0, 0);
3783 } else if (offscreen_target_frame_buffer_.get()) {
3784 return offscreen_size_;
3785 } else {
3786 return surface_->GetSize();
3790 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3791 Framebuffer* framebuffer =
3792 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3793 if (framebuffer) {
3794 return framebuffer->GetReadBufferTextureType();
3795 } else { // Back buffer.
3796 if (back_buffer_read_buffer_ == GL_NONE)
3797 return 0;
3798 return GL_UNSIGNED_BYTE;
3802 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3803 Framebuffer* framebuffer =
3804 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3805 if (framebuffer) {
3806 return framebuffer->GetReadBufferInternalFormat();
3807 } else { // Back buffer.
3808 if (back_buffer_read_buffer_ == GL_NONE)
3809 return 0;
3810 if (offscreen_target_frame_buffer_.get()) {
3811 return offscreen_target_color_format_;
3813 return back_buffer_color_format_;
3817 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3818 if (!offscreen_saved_color_texture_info_.get())
3819 return;
3820 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3821 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3822 texture_manager()->SetLevelInfo(
3823 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3824 0, // level
3825 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3826 1, // depth
3827 0, // border
3828 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3829 texture_manager()->SetParameteri(
3830 "UpdateParentTextureInfo",
3831 GetErrorState(),
3832 offscreen_saved_color_texture_info_.get(),
3833 GL_TEXTURE_MAG_FILTER,
3834 GL_LINEAR);
3835 texture_manager()->SetParameteri(
3836 "UpdateParentTextureInfo",
3837 GetErrorState(),
3838 offscreen_saved_color_texture_info_.get(),
3839 GL_TEXTURE_MIN_FILTER,
3840 GL_LINEAR);
3841 texture_manager()->SetParameteri(
3842 "UpdateParentTextureInfo",
3843 GetErrorState(),
3844 offscreen_saved_color_texture_info_.get(),
3845 GL_TEXTURE_WRAP_S,
3846 GL_CLAMP_TO_EDGE);
3847 texture_manager()->SetParameteri(
3848 "UpdateParentTextureInfo",
3849 GetErrorState(),
3850 offscreen_saved_color_texture_info_.get(),
3851 GL_TEXTURE_WRAP_T,
3852 GL_CLAMP_TO_EDGE);
3853 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3854 &state_, target);
3855 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3858 void GLES2DecoderImpl::SetResizeCallback(
3859 const base::Callback<void(gfx::Size, float)>& callback) {
3860 resize_callback_ = callback;
3863 Logger* GLES2DecoderImpl::GetLogger() {
3864 return &logger_;
3867 void GLES2DecoderImpl::BeginDecoding() {
3868 gpu_tracer_->BeginDecoding();
3869 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3870 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3871 (*cb_command_trace_category_ != 0);
3872 query_manager_->ProcessFrameBeginUpdates();
3875 void GLES2DecoderImpl::EndDecoding() {
3876 gpu_tracer_->EndDecoding();
3879 ErrorState* GLES2DecoderImpl::GetErrorState() {
3880 return state_.GetErrorState();
3883 void GLES2DecoderImpl::SetShaderCacheCallback(
3884 const ShaderCacheCallback& callback) {
3885 shader_cache_callback_ = callback;
3888 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3889 const WaitSyncPointCallback& callback) {
3890 wait_sync_point_callback_ = callback;
3893 AsyncPixelTransferManager*
3894 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3895 return async_pixel_transfer_manager_.get();
3898 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3899 async_pixel_transfer_manager_.reset();
3902 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3903 AsyncPixelTransferManager* manager) {
3904 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3907 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3908 uint32* service_texture_id) {
3909 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3910 if (texture_ref) {
3911 *service_texture_id = texture_ref->service_id();
3912 return true;
3914 return false;
3917 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3918 return texture_state_.texture_upload_count +
3919 async_pixel_transfer_manager_->GetTextureUploadCount();
3922 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3923 return texture_state_.total_texture_upload_time +
3924 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3927 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3928 return total_processing_commands_time_;
3931 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3932 total_processing_commands_time_ += time;
3935 void GLES2DecoderImpl::Destroy(bool have_context) {
3936 if (!initialized())
3937 return;
3939 DCHECK(!have_context || context_->IsCurrent(NULL));
3941 // Unbind everything.
3942 state_.vertex_attrib_manager = NULL;
3943 state_.default_vertex_attrib_manager = NULL;
3944 state_.texture_units.clear();
3945 state_.bound_array_buffer = NULL;
3946 state_.bound_copy_read_buffer = NULL;
3947 state_.bound_copy_write_buffer = NULL;
3948 state_.bound_pixel_pack_buffer = NULL;
3949 state_.bound_pixel_unpack_buffer = NULL;
3950 state_.bound_transform_feedback_buffer = NULL;
3951 state_.bound_uniform_buffer = NULL;
3952 framebuffer_state_.bound_read_framebuffer = NULL;
3953 framebuffer_state_.bound_draw_framebuffer = NULL;
3954 state_.bound_renderbuffer = NULL;
3955 state_.bound_valuebuffer = NULL;
3957 if (offscreen_saved_color_texture_info_.get()) {
3958 DCHECK(offscreen_target_color_texture_);
3959 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3960 offscreen_saved_color_texture_->id());
3961 offscreen_saved_color_texture_->Invalidate();
3962 offscreen_saved_color_texture_info_ = NULL;
3964 if (have_context) {
3965 if (copy_texture_CHROMIUM_.get()) {
3966 copy_texture_CHROMIUM_->Destroy();
3967 copy_texture_CHROMIUM_.reset();
3970 clear_framebuffer_blit_.reset();
3972 if (state_.current_program.get()) {
3973 program_manager()->UnuseProgram(shader_manager(),
3974 state_.current_program.get());
3977 if (attrib_0_buffer_id_) {
3978 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3980 if (fixed_attrib_buffer_id_) {
3981 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3984 if (validation_texture_) {
3985 glDeleteTextures(1, &validation_texture_);
3986 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3987 glDeleteFramebuffersEXT(1, &validation_fbo_);
3990 if (offscreen_target_frame_buffer_.get())
3991 offscreen_target_frame_buffer_->Destroy();
3992 if (offscreen_target_color_texture_.get())
3993 offscreen_target_color_texture_->Destroy();
3994 if (offscreen_target_color_render_buffer_.get())
3995 offscreen_target_color_render_buffer_->Destroy();
3996 if (offscreen_target_depth_render_buffer_.get())
3997 offscreen_target_depth_render_buffer_->Destroy();
3998 if (offscreen_target_stencil_render_buffer_.get())
3999 offscreen_target_stencil_render_buffer_->Destroy();
4000 if (offscreen_saved_frame_buffer_.get())
4001 offscreen_saved_frame_buffer_->Destroy();
4002 if (offscreen_saved_color_texture_.get())
4003 offscreen_saved_color_texture_->Destroy();
4004 if (offscreen_resolved_frame_buffer_.get())
4005 offscreen_resolved_frame_buffer_->Destroy();
4006 if (offscreen_resolved_color_texture_.get())
4007 offscreen_resolved_color_texture_->Destroy();
4008 } else {
4009 if (offscreen_target_frame_buffer_.get())
4010 offscreen_target_frame_buffer_->Invalidate();
4011 if (offscreen_target_color_texture_.get())
4012 offscreen_target_color_texture_->Invalidate();
4013 if (offscreen_target_color_render_buffer_.get())
4014 offscreen_target_color_render_buffer_->Invalidate();
4015 if (offscreen_target_depth_render_buffer_.get())
4016 offscreen_target_depth_render_buffer_->Invalidate();
4017 if (offscreen_target_stencil_render_buffer_.get())
4018 offscreen_target_stencil_render_buffer_->Invalidate();
4019 if (offscreen_saved_frame_buffer_.get())
4020 offscreen_saved_frame_buffer_->Invalidate();
4021 if (offscreen_saved_color_texture_.get())
4022 offscreen_saved_color_texture_->Invalidate();
4023 if (offscreen_resolved_frame_buffer_.get())
4024 offscreen_resolved_frame_buffer_->Invalidate();
4025 if (offscreen_resolved_color_texture_.get())
4026 offscreen_resolved_color_texture_->Invalidate();
4029 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4030 // Otherwise, we can leak objects. http://crbug.com/258772.
4031 // state_.current_program must be reset before group_ is reset because
4032 // the later deletes the ProgramManager object that referred by
4033 // state_.current_program object.
4034 state_.current_program = NULL;
4036 copy_texture_CHROMIUM_.reset();
4037 clear_framebuffer_blit_.reset();
4039 if (query_manager_.get()) {
4040 query_manager_->Destroy(have_context);
4041 query_manager_.reset();
4044 if (vertex_array_manager_ .get()) {
4045 vertex_array_manager_->Destroy(have_context);
4046 vertex_array_manager_.reset();
4049 if (image_manager_.get()) {
4050 image_manager_->Destroy(have_context);
4051 image_manager_.reset();
4054 offscreen_target_frame_buffer_.reset();
4055 offscreen_target_color_texture_.reset();
4056 offscreen_target_color_render_buffer_.reset();
4057 offscreen_target_depth_render_buffer_.reset();
4058 offscreen_target_stencil_render_buffer_.reset();
4059 offscreen_saved_frame_buffer_.reset();
4060 offscreen_saved_color_texture_.reset();
4061 offscreen_resolved_frame_buffer_.reset();
4062 offscreen_resolved_color_texture_.reset();
4064 // Need to release these before releasing |group_| which may own the
4065 // ShaderTranslatorCache.
4066 fragment_translator_ = NULL;
4067 vertex_translator_ = NULL;
4069 // Should destroy the transfer manager before the texture manager held
4070 // by the context group.
4071 async_pixel_transfer_manager_.reset();
4073 // Destroy the GPU Tracer which may own some in process GPU Timings.
4074 if (gpu_tracer_) {
4075 gpu_tracer_->Destroy(have_context);
4076 gpu_tracer_.reset();
4079 if (group_.get()) {
4080 framebuffer_manager()->RemoveObserver(this);
4081 group_->Destroy(this, have_context);
4082 group_ = NULL;
4085 if (context_.get()) {
4086 context_->ReleaseCurrent(NULL);
4087 context_ = NULL;
4090 #if defined(OS_MACOSX)
4091 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4092 it != texture_to_io_surface_map_.end(); ++it) {
4093 CFRelease(it->second);
4095 texture_to_io_surface_map_.clear();
4096 #endif
4099 void GLES2DecoderImpl::SetSurface(
4100 const scoped_refptr<gfx::GLSurface>& surface) {
4101 DCHECK(context_->IsCurrent(NULL));
4102 DCHECK(surface_.get());
4103 surface_ = surface;
4104 RestoreCurrentFramebufferBindings();
4107 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4108 if (!offscreen_saved_color_texture_.get()) {
4109 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4110 return;
4112 if (!offscreen_saved_color_texture_info_.get()) {
4113 GLuint service_id = offscreen_saved_color_texture_->id();
4114 offscreen_saved_color_texture_info_ = TextureRef::Create(
4115 texture_manager(), 0, service_id);
4116 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4117 GL_TEXTURE_2D);
4118 UpdateParentTextureInfo();
4120 mailbox_manager()->ProduceTexture(
4121 mailbox, offscreen_saved_color_texture_info_->texture());
4124 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4125 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4126 if (!is_offscreen) {
4127 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4128 << " with an onscreen framebuffer.";
4129 return false;
4132 if (offscreen_size_ == size)
4133 return true;
4135 offscreen_size_ = size;
4136 int w = offscreen_size_.width();
4137 int h = offscreen_size_.height();
4138 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4139 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4140 << "to allocate storage due to excessive dimensions.";
4141 return false;
4144 // Reallocate the offscreen target buffers.
4145 DCHECK(offscreen_target_color_format_);
4146 if (IsOffscreenBufferMultisampled()) {
4147 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4148 feature_info_.get(),
4149 offscreen_size_,
4150 offscreen_target_color_format_,
4151 offscreen_target_samples_)) {
4152 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4153 << "to allocate storage for offscreen target color buffer.";
4154 return false;
4156 } else {
4157 if (!offscreen_target_color_texture_->AllocateStorage(
4158 offscreen_size_, offscreen_target_color_format_, false)) {
4159 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4160 << "to allocate storage for offscreen target color texture.";
4161 return false;
4164 if (offscreen_target_depth_format_ &&
4165 !offscreen_target_depth_render_buffer_->AllocateStorage(
4166 feature_info_.get(),
4167 offscreen_size_,
4168 offscreen_target_depth_format_,
4169 offscreen_target_samples_)) {
4170 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4171 << "to allocate storage for offscreen target depth buffer.";
4172 return false;
4174 if (offscreen_target_stencil_format_ &&
4175 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4176 feature_info_.get(),
4177 offscreen_size_,
4178 offscreen_target_stencil_format_,
4179 offscreen_target_samples_)) {
4180 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4181 << "to allocate storage for offscreen target stencil buffer.";
4182 return false;
4185 // Attach the offscreen target buffers to the target frame buffer.
4186 if (IsOffscreenBufferMultisampled()) {
4187 offscreen_target_frame_buffer_->AttachRenderBuffer(
4188 GL_COLOR_ATTACHMENT0,
4189 offscreen_target_color_render_buffer_.get());
4190 } else {
4191 offscreen_target_frame_buffer_->AttachRenderTexture(
4192 offscreen_target_color_texture_.get());
4194 if (offscreen_target_depth_format_) {
4195 offscreen_target_frame_buffer_->AttachRenderBuffer(
4196 GL_DEPTH_ATTACHMENT,
4197 offscreen_target_depth_render_buffer_.get());
4199 const bool packed_depth_stencil =
4200 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4201 if (packed_depth_stencil) {
4202 offscreen_target_frame_buffer_->AttachRenderBuffer(
4203 GL_STENCIL_ATTACHMENT,
4204 offscreen_target_depth_render_buffer_.get());
4205 } else if (offscreen_target_stencil_format_) {
4206 offscreen_target_frame_buffer_->AttachRenderBuffer(
4207 GL_STENCIL_ATTACHMENT,
4208 offscreen_target_stencil_render_buffer_.get());
4211 if (offscreen_target_frame_buffer_->CheckStatus() !=
4212 GL_FRAMEBUFFER_COMPLETE) {
4213 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4214 << "because offscreen FBO was incomplete.";
4215 return false;
4218 // Clear the target frame buffer.
4220 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4221 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f);
4222 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4223 glClearStencil(0);
4224 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4225 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4226 glClearDepth(0);
4227 state_.SetDeviceDepthMask(GL_TRUE);
4228 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4229 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4230 RestoreClearState();
4233 // Destroy the offscreen resolved framebuffers.
4234 if (offscreen_resolved_frame_buffer_.get())
4235 offscreen_resolved_frame_buffer_->Destroy();
4236 if (offscreen_resolved_color_texture_.get())
4237 offscreen_resolved_color_texture_->Destroy();
4238 offscreen_resolved_color_texture_.reset();
4239 offscreen_resolved_frame_buffer_.reset();
4241 return true;
4244 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4245 const void* cmd_data) {
4246 const gles2::cmds::ResizeCHROMIUM& c =
4247 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4248 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4249 return error::kDeferCommandUntilLater;
4251 GLuint width = static_cast<GLuint>(c.width);
4252 GLuint height = static_cast<GLuint>(c.height);
4253 GLfloat scale_factor = c.scale_factor;
4254 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4256 width = std::max(1U, width);
4257 height = std::max(1U, height);
4259 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4260 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4261 // Make sure that we are done drawing to the back buffer before resizing.
4262 glFinish();
4263 #endif
4264 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4265 if (is_offscreen) {
4266 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4267 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4268 << "ResizeOffscreenFrameBuffer failed.";
4269 return error::kLostContext;
4273 if (!resize_callback_.is_null()) {
4274 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4275 DCHECK(context_->IsCurrent(surface_.get()));
4276 if (!context_->IsCurrent(surface_.get())) {
4277 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4278 << "current after resize callback.";
4279 return error::kLostContext;
4283 return error::kNoError;
4286 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4287 if (command_id > kStartPoint && command_id < kNumCommands) {
4288 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4290 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4293 // Decode a command, and call the corresponding GL functions.
4294 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4295 // of commands at once, and is now only used for tests that need to track
4296 // individual commands.
4297 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4298 unsigned int arg_count,
4299 const void* cmd_data) {
4300 return DoCommands(1, cmd_data, arg_count + 1, 0);
4303 // Decode multiple commands, and call the corresponding GL functions.
4304 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4305 // changed by a (malicious) client at any time, so if validation has to happen,
4306 // it should operate on a copy of them.
4307 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4308 // interest of performance in this critical execution loop.
4309 template <bool DebugImpl>
4310 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4311 const void* buffer,
4312 int num_entries,
4313 int* entries_processed) {
4314 commands_to_process_ = num_commands;
4315 error::Error result = error::kNoError;
4316 const CommandBufferEntry* cmd_data =
4317 static_cast<const CommandBufferEntry*>(buffer);
4318 int process_pos = 0;
4319 unsigned int command = 0;
4321 while (process_pos < num_entries && result == error::kNoError &&
4322 commands_to_process_--) {
4323 const unsigned int size = cmd_data->value_header.size;
4324 command = cmd_data->value_header.command;
4326 if (size == 0) {
4327 result = error::kInvalidSize;
4328 break;
4331 if (static_cast<int>(size) + process_pos > num_entries) {
4332 result = error::kOutOfBounds;
4333 break;
4336 if (DebugImpl) {
4337 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4338 GetCommandName(command));
4340 if (log_commands()) {
4341 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4342 << "cmd: " << GetCommandName(command);
4346 const unsigned int arg_count = size - 1;
4347 unsigned int command_index = command - kStartPoint - 1;
4348 if (command_index < arraysize(command_info)) {
4349 const CommandInfo& info = command_info[command_index];
4350 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4351 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4352 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4353 bool doing_gpu_trace = false;
4354 if (DebugImpl && gpu_trace_commands_) {
4355 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4356 doing_gpu_trace = true;
4357 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4358 GetCommandName(command),
4359 kTraceDecoder);
4363 uint32 immediate_data_size = (arg_count - info_arg_count) *
4364 sizeof(CommandBufferEntry); // NOLINT
4366 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4368 if (DebugImpl && doing_gpu_trace)
4369 gpu_tracer_->End(kTraceDecoder);
4371 if (DebugImpl && debug()) {
4372 GLenum error;
4373 while ((error = glGetError()) != GL_NO_ERROR) {
4374 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4375 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4376 << " : " << GetCommandName(command);
4377 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4380 } else {
4381 result = error::kInvalidArguments;
4383 } else {
4384 result = DoCommonCommand(command, arg_count, cmd_data);
4387 if (DebugImpl) {
4388 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4389 GetCommandName(command));
4392 if (result == error::kNoError &&
4393 current_decoder_error_ != error::kNoError) {
4394 result = current_decoder_error_;
4395 current_decoder_error_ = error::kNoError;
4398 if (result != error::kDeferCommandUntilLater) {
4399 process_pos += size;
4400 cmd_data += size;
4404 if (entries_processed)
4405 *entries_processed = process_pos;
4407 if (error::IsError(result)) {
4408 LOG(ERROR) << "Error: " << result << " for Command "
4409 << GetCommandName(command);
4412 return result;
4415 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4416 const void* buffer,
4417 int num_entries,
4418 int* entries_processed) {
4419 if (gpu_debug_commands_) {
4420 return DoCommandsImpl<true>(
4421 num_commands, buffer, num_entries, entries_processed);
4422 } else {
4423 return DoCommandsImpl<false>(
4424 num_commands, buffer, num_entries, entries_processed);
4428 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4429 buffer_manager()->RemoveBuffer(client_id);
4432 void GLES2DecoderImpl::DoFinish() {
4433 glFinish();
4434 ProcessPendingReadPixels(true);
4435 ProcessPendingQueries(true);
4438 void GLES2DecoderImpl::DoFlush() {
4439 glFlush();
4440 ProcessPendingQueries(false);
4443 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4444 GLuint texture_index = texture_unit - GL_TEXTURE0;
4445 if (texture_index >= state_.texture_units.size()) {
4446 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4447 "glActiveTexture", texture_unit, "texture_unit");
4448 return;
4450 state_.active_texture_unit = texture_index;
4451 glActiveTexture(texture_unit);
4454 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4455 Buffer* buffer = NULL;
4456 GLuint service_id = 0;
4457 if (client_id != 0) {
4458 buffer = GetBuffer(client_id);
4459 if (!buffer) {
4460 if (!group_->bind_generates_resource()) {
4461 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4462 "glBindBuffer",
4463 "id not generated by glGenBuffers");
4464 return;
4467 // It's a new id so make a buffer buffer for it.
4468 glGenBuffersARB(1, &service_id);
4469 CreateBuffer(client_id, service_id);
4470 buffer = GetBuffer(client_id);
4473 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4474 if (buffer) {
4475 if (!buffer_manager()->SetTarget(buffer, target)) {
4476 LOCAL_SET_GL_ERROR(
4477 GL_INVALID_OPERATION,
4478 "glBindBuffer", "buffer bound to more than 1 target");
4479 return;
4481 service_id = buffer->service_id();
4483 state_.SetBoundBuffer(target, buffer);
4484 glBindBuffer(target, service_id);
4487 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4488 Framebuffer* framebuffer =
4489 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4490 if (framebuffer)
4491 return framebuffer->HasAlphaMRT();
4492 return BackBufferHasAlpha();
4495 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4496 Framebuffer* framebuffer =
4497 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4498 if (framebuffer) {
4499 return framebuffer->HasDepthAttachment();
4501 if (offscreen_target_frame_buffer_.get()) {
4502 return offscreen_target_depth_format_ != 0;
4504 return back_buffer_has_depth_;
4507 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4508 Framebuffer* framebuffer =
4509 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4510 if (framebuffer) {
4511 return framebuffer->HasStencilAttachment();
4513 if (offscreen_target_frame_buffer_.get()) {
4514 return offscreen_target_stencil_format_ != 0 ||
4515 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4517 return back_buffer_has_stencil_;
4520 void GLES2DecoderImpl::ApplyDirtyState() {
4521 if (framebuffer_state_.clear_state_dirty) {
4522 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha();
4523 state_.SetDeviceColorMask(state_.color_mask_red,
4524 state_.color_mask_green,
4525 state_.color_mask_blue,
4526 state_.color_mask_alpha && have_alpha);
4528 bool have_depth = BoundFramebufferHasDepthAttachment();
4529 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4531 bool have_stencil = BoundFramebufferHasStencilAttachment();
4532 state_.SetDeviceStencilMaskSeparate(
4533 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4534 state_.SetDeviceStencilMaskSeparate(
4535 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4537 state_.SetDeviceCapabilityState(
4538 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4539 state_.SetDeviceCapabilityState(
4540 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4541 framebuffer_state_.clear_state_dirty = false;
4545 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4546 return (offscreen_target_frame_buffer_.get())
4547 ? offscreen_target_frame_buffer_->id()
4548 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4551 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4552 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4553 "context", logger_.GetLogPrefix());
4554 // Restore the Framebuffer first because of bugs in Intel drivers.
4555 // Intel drivers incorrectly clip the viewport settings to
4556 // the size of the current framebuffer object.
4557 RestoreFramebufferBindings();
4558 state_.RestoreState(prev_state);
4561 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4562 GLuint service_id =
4563 framebuffer_state_.bound_draw_framebuffer.get()
4564 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4565 : GetBackbufferServiceId();
4566 if (!features().chromium_framebuffer_multisample) {
4567 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4568 } else {
4569 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4570 service_id = framebuffer_state_.bound_read_framebuffer.get()
4571 ? framebuffer_state_.bound_read_framebuffer->service_id()
4572 : GetBackbufferServiceId();
4573 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4575 OnFboChanged();
4578 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4579 state_.RestoreRenderbufferBindings();
4582 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4583 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4584 if (texture) {
4585 GLenum target = texture->target();
4586 glBindTexture(target, service_id);
4587 glTexParameteri(
4588 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4589 glTexParameteri(
4590 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4591 glTexParameteri(
4592 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4593 glTexParameteri(
4594 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4595 RestoreTextureUnitBindings(state_.active_texture_unit);
4599 void GLES2DecoderImpl::ClearAllAttributes() const {
4600 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4601 // other VAOs.
4602 if (feature_info_->feature_flags().native_vertex_array_object)
4603 glBindVertexArrayOES(0);
4605 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4606 if (i != 0) // Never disable attribute 0
4607 glDisableVertexAttribArray(i);
4608 if (features().angle_instanced_arrays)
4609 glVertexAttribDivisorANGLE(i, 0);
4613 void GLES2DecoderImpl::RestoreAllAttributes() const {
4614 state_.RestoreVertexAttribs();
4617 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4618 state_.SetIgnoreCachedStateForTest(ignore);
4621 void GLES2DecoderImpl::OnFboChanged() const {
4622 if (workarounds().restore_scissor_on_fbo_change)
4623 state_.fbo_binding_for_scissor_workaround_dirty = true;
4625 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4626 GLint bound_fbo_unsigned = -1;
4627 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4628 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4629 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4630 surface_->NotifyWasBound();
4634 // Called after the FBO is checked for completeness.
4635 void GLES2DecoderImpl::OnUseFramebuffer() const {
4636 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4637 state_.fbo_binding_for_scissor_workaround_dirty = false;
4638 // The driver forgets the correct scissor when modifying the FBO binding.
4639 glScissor(state_.scissor_x,
4640 state_.scissor_y,
4641 state_.scissor_width,
4642 state_.scissor_height);
4644 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4645 // it's unclear how this bug works.
4646 glFlush();
4650 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4651 Framebuffer* framebuffer = NULL;
4652 GLuint service_id = 0;
4653 if (client_id != 0) {
4654 framebuffer = GetFramebuffer(client_id);
4655 if (!framebuffer) {
4656 if (!group_->bind_generates_resource()) {
4657 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4658 "glBindFramebuffer",
4659 "id not generated by glGenFramebuffers");
4660 return;
4663 // It's a new id so make a framebuffer framebuffer for it.
4664 glGenFramebuffersEXT(1, &service_id);
4665 CreateFramebuffer(client_id, service_id);
4666 framebuffer = GetFramebuffer(client_id);
4667 } else {
4668 service_id = framebuffer->service_id();
4670 framebuffer->MarkAsValid();
4672 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4674 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4675 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4678 // vmiura: This looks like dup code
4679 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4680 framebuffer_state_.bound_read_framebuffer = framebuffer;
4683 framebuffer_state_.clear_state_dirty = true;
4685 // If we are rendering to the backbuffer get the FBO id for any simulated
4686 // backbuffer.
4687 if (framebuffer == NULL) {
4688 service_id = GetBackbufferServiceId();
4691 glBindFramebufferEXT(target, service_id);
4692 OnFboChanged();
4695 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4696 Renderbuffer* renderbuffer = NULL;
4697 GLuint service_id = 0;
4698 if (client_id != 0) {
4699 renderbuffer = GetRenderbuffer(client_id);
4700 if (!renderbuffer) {
4701 if (!group_->bind_generates_resource()) {
4702 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4703 "glBindRenderbuffer",
4704 "id not generated by glGenRenderbuffers");
4705 return;
4708 // It's a new id so make a renderbuffer for it.
4709 glGenRenderbuffersEXT(1, &service_id);
4710 CreateRenderbuffer(client_id, service_id);
4711 renderbuffer = GetRenderbuffer(client_id);
4712 } else {
4713 service_id = renderbuffer->service_id();
4715 renderbuffer->MarkAsValid();
4717 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4718 state_.bound_renderbuffer = renderbuffer;
4719 state_.bound_renderbuffer_valid = true;
4720 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4723 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4724 TextureRef* texture_ref = NULL;
4725 GLuint service_id = 0;
4726 if (client_id != 0) {
4727 texture_ref = GetTexture(client_id);
4728 if (!texture_ref) {
4729 if (!group_->bind_generates_resource()) {
4730 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4731 "glBindTexture",
4732 "id not generated by glGenTextures");
4733 return;
4736 // It's a new id so make a texture texture for it.
4737 glGenTextures(1, &service_id);
4738 DCHECK_NE(0u, service_id);
4739 CreateTexture(client_id, service_id);
4740 texture_ref = GetTexture(client_id);
4742 } else {
4743 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4746 // Check the texture exists
4747 if (texture_ref) {
4748 Texture* texture = texture_ref->texture();
4749 // Check that we are not trying to bind it to a different target.
4750 if (texture->target() != 0 && texture->target() != target) {
4751 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4752 "glBindTexture",
4753 "texture bound to more than 1 target.");
4754 return;
4756 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4757 if (texture->target() == 0) {
4758 texture_manager()->SetTarget(texture_ref, target);
4760 glBindTexture(target, texture->service_id());
4761 } else {
4762 glBindTexture(target, 0);
4765 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4766 unit.bind_target = target;
4767 switch (target) {
4768 case GL_TEXTURE_2D:
4769 unit.bound_texture_2d = texture_ref;
4770 break;
4771 case GL_TEXTURE_CUBE_MAP:
4772 unit.bound_texture_cube_map = texture_ref;
4773 break;
4774 case GL_TEXTURE_EXTERNAL_OES:
4775 unit.bound_texture_external_oes = texture_ref;
4776 break;
4777 case GL_TEXTURE_RECTANGLE_ARB:
4778 unit.bound_texture_rectangle_arb = texture_ref;
4779 break;
4780 case GL_TEXTURE_3D:
4781 unit.bound_texture_3d = texture_ref;
4782 break;
4783 case GL_TEXTURE_2D_ARRAY:
4784 unit.bound_texture_2d_array = texture_ref;
4785 break;
4786 default:
4787 NOTREACHED(); // Validation should prevent us getting here.
4788 break;
4792 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4793 if (state_.vertex_attrib_manager->Enable(index, false)) {
4794 if (index != 0 ||
4795 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4796 glDisableVertexAttribArray(index);
4798 } else {
4799 LOCAL_SET_GL_ERROR(
4800 GL_INVALID_VALUE,
4801 "glDisableVertexAttribArray", "index out of range");
4805 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4806 GLsizei numAttachments,
4807 const GLenum* attachments) {
4808 if (workarounds().disable_discard_framebuffer)
4809 return;
4811 Framebuffer* framebuffer =
4812 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4814 // Validates the attachments. If one of them fails
4815 // the whole command fails.
4816 for (GLsizei i = 0; i < numAttachments; ++i) {
4817 if ((framebuffer &&
4818 !validators_->attachment.IsValid(attachments[i])) ||
4819 (!framebuffer &&
4820 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4821 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4822 "glDiscardFramebufferEXT", attachments[i], "attachments");
4823 return;
4827 // Marks each one of them as not cleared
4828 for (GLsizei i = 0; i < numAttachments; ++i) {
4829 if (framebuffer) {
4830 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4831 texture_manager(),
4832 attachments[i],
4833 false);
4834 } else {
4835 switch (attachments[i]) {
4836 case GL_COLOR_EXT:
4837 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4838 break;
4839 case GL_DEPTH_EXT:
4840 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4841 case GL_STENCIL_EXT:
4842 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4843 break;
4844 default:
4845 NOTREACHED();
4846 break;
4851 // If the default framebuffer is bound but we are still rendering to an
4852 // FBO, translate attachment names that refer to default framebuffer
4853 // channels to corresponding framebuffer attachments.
4854 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4855 for (GLsizei i = 0; i < numAttachments; ++i) {
4856 GLenum attachment = attachments[i];
4857 if (!framebuffer && GetBackbufferServiceId()) {
4858 switch (attachment) {
4859 case GL_COLOR_EXT:
4860 attachment = GL_COLOR_ATTACHMENT0;
4861 break;
4862 case GL_DEPTH_EXT:
4863 attachment = GL_DEPTH_ATTACHMENT;
4864 break;
4865 case GL_STENCIL_EXT:
4866 attachment = GL_STENCIL_ATTACHMENT;
4867 break;
4868 default:
4869 NOTREACHED();
4870 return;
4873 translated_attachments[i] = attachment;
4876 ScopedRenderTo do_render(framebuffer);
4877 if (feature_info_->gl_version_info().is_es3) {
4878 glInvalidateFramebuffer(
4879 target, numAttachments, translated_attachments.get());
4880 } else {
4881 glDiscardFramebufferEXT(
4882 target, numAttachments, translated_attachments.get());
4886 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4887 if (state_.vertex_attrib_manager->Enable(index, true)) {
4888 glEnableVertexAttribArray(index);
4889 } else {
4890 LOCAL_SET_GL_ERROR(
4891 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4895 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4896 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4897 &state_, target);
4898 if (!texture_ref ||
4899 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4900 LOCAL_SET_GL_ERROR(
4901 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4902 return;
4905 if (target == GL_TEXTURE_CUBE_MAP) {
4906 for (int i = 0; i < 6; ++i) {
4907 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4908 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4909 LOCAL_SET_GL_ERROR(
4910 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4911 return;
4914 } else {
4915 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4916 LOCAL_SET_GL_ERROR(
4917 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4918 return;
4922 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4923 // Workaround for Mac driver bug. In the large scheme of things setting
4924 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4925 // hit so there's probably no need to make this conditional. The bug appears
4926 // to be that if the filtering mode is set to something that doesn't require
4927 // mipmaps for rendering, or is never set to something other than the default,
4928 // then glGenerateMipmap misbehaves.
4929 if (workarounds().set_texture_filter_before_generating_mipmap) {
4930 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4932 glGenerateMipmapEXT(target);
4933 if (workarounds().set_texture_filter_before_generating_mipmap) {
4934 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4935 texture_ref->texture()->min_filter());
4937 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4938 if (error == GL_NO_ERROR) {
4939 texture_manager()->MarkMipmapsGenerated(texture_ref);
4943 bool GLES2DecoderImpl::GetHelper(
4944 GLenum pname, GLint* params, GLsizei* num_written) {
4945 DCHECK(num_written);
4946 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4947 switch (pname) {
4948 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4949 *num_written = 1;
4950 // Return the GL implementation's preferred format and (see below type)
4951 // if we have the GL extension that exposes this. This allows the GPU
4952 // client to use the implementation's preferred format for glReadPixels
4953 // for optimisation.
4955 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4956 // case when requested on integer/floating point buffers but which is
4957 // acceptable on GLES2 and with the GL_OES_read_format extension.
4959 // Therefore if an error occurs we swallow the error and use the
4960 // internal implementation.
4961 if (params) {
4962 if (context_->HasExtension("GL_OES_read_format")) {
4963 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4964 GetErrorState());
4965 glGetIntegerv(pname, params);
4966 if (glGetError() == GL_NO_ERROR)
4967 return true;
4969 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4970 GetBoundReadFrameBufferInternalFormat());
4972 return true;
4973 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4974 *num_written = 1;
4975 if (params) {
4976 if (context_->HasExtension("GL_OES_read_format")) {
4977 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4978 GetErrorState());
4979 glGetIntegerv(pname, params);
4980 if (glGetError() == GL_NO_ERROR)
4981 return true;
4983 *params = GLES2Util::GetPreferredGLReadPixelsType(
4984 GetBoundReadFrameBufferInternalFormat(),
4985 GetBoundReadFrameBufferTextureType());
4987 return true;
4988 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4989 *num_written = 1;
4990 if (params) {
4991 *params = group_->max_fragment_uniform_vectors();
4993 return true;
4994 case GL_MAX_VARYING_VECTORS:
4995 *num_written = 1;
4996 if (params) {
4997 *params = group_->max_varying_vectors();
4999 return true;
5000 case GL_MAX_VERTEX_UNIFORM_VECTORS:
5001 *num_written = 1;
5002 if (params) {
5003 *params = group_->max_vertex_uniform_vectors();
5005 return true;
5008 if (unsafe_es3_apis_enabled()) {
5009 switch (pname) {
5010 case GL_MAX_VARYING_COMPONENTS: {
5011 if (feature_info_->gl_version_info().is_es) {
5012 // We can just delegate this query to the driver.
5013 return false;
5016 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5017 // OpenGL core profile, so for simplicity, just compute it
5018 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5019 // configurations.
5020 GLint max_varying_vectors = 0;
5021 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5022 *num_written = 1;
5023 if (params) {
5024 *params = max_varying_vectors * 4;
5026 return true;
5028 case GL_READ_BUFFER:
5029 *num_written = 1;
5030 if (params) {
5031 Framebuffer* framebuffer =
5032 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5033 GLenum read_buffer;
5034 if (framebuffer) {
5035 read_buffer = framebuffer->read_buffer();
5036 } else {
5037 read_buffer = back_buffer_read_buffer_;
5039 *params = static_cast<GLint>(read_buffer);
5041 return true;
5044 switch (pname) {
5045 case GL_MAX_VIEWPORT_DIMS:
5046 if (offscreen_target_frame_buffer_.get()) {
5047 *num_written = 2;
5048 if (params) {
5049 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5050 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5052 return true;
5054 return false;
5055 case GL_MAX_SAMPLES:
5056 *num_written = 1;
5057 if (params) {
5058 params[0] = renderbuffer_manager()->max_samples();
5060 return true;
5061 case GL_MAX_RENDERBUFFER_SIZE:
5062 *num_written = 1;
5063 if (params) {
5064 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5066 return true;
5067 case GL_MAX_TEXTURE_SIZE:
5068 *num_written = 1;
5069 if (params) {
5070 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5072 return true;
5073 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5074 *num_written = 1;
5075 if (params) {
5076 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5078 return true;
5079 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5080 *num_written = 1;
5081 if (params) {
5082 params[0] = group_->max_color_attachments();
5084 return true;
5085 case GL_MAX_DRAW_BUFFERS_ARB:
5086 *num_written = 1;
5087 if (params) {
5088 params[0] = group_->max_draw_buffers();
5090 return true;
5091 case GL_ALPHA_BITS:
5092 *num_written = 1;
5093 if (params) {
5094 GLint v = 0;
5095 Framebuffer* framebuffer =
5096 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5097 if (framebuffer) {
5098 if (framebuffer->HasAlphaMRT() &&
5099 framebuffer->HasSameInternalFormatsMRT()) {
5100 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5101 glGetFramebufferAttachmentParameterivEXT(
5102 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5103 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5104 } else {
5105 glGetIntegerv(GL_ALPHA_BITS, &v);
5108 } else {
5109 v = (BackBufferHasAlpha() ? 8 : 0);
5111 params[0] = v;
5113 return true;
5114 case GL_DEPTH_BITS:
5115 *num_written = 1;
5116 if (params) {
5117 GLint v = 0;
5118 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5119 Framebuffer* framebuffer =
5120 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5121 if (framebuffer) {
5122 glGetFramebufferAttachmentParameterivEXT(
5123 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5124 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5125 } else {
5126 v = (back_buffer_has_depth_ ? 24 : 0);
5128 } else {
5129 glGetIntegerv(GL_DEPTH_BITS, &v);
5131 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5133 return true;
5134 case GL_RED_BITS:
5135 case GL_GREEN_BITS:
5136 case GL_BLUE_BITS:
5137 *num_written = 1;
5138 if (params) {
5139 GLint v = 0;
5140 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5141 Framebuffer* framebuffer =
5142 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5143 if (framebuffer) {
5144 GLenum framebuffer_enum = 0;
5145 switch (pname) {
5146 case GL_RED_BITS:
5147 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5148 break;
5149 case GL_GREEN_BITS:
5150 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5151 break;
5152 case GL_BLUE_BITS:
5153 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5154 break;
5156 glGetFramebufferAttachmentParameterivEXT(
5157 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5158 } else {
5159 v = 8;
5161 } else {
5162 glGetIntegerv(pname, &v);
5164 params[0] = v;
5166 return true;
5167 case GL_STENCIL_BITS:
5168 *num_written = 1;
5169 if (params) {
5170 GLint v = 0;
5171 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5172 Framebuffer* framebuffer =
5173 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5174 if (framebuffer) {
5175 glGetFramebufferAttachmentParameterivEXT(
5176 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5177 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5178 } else {
5179 v = (back_buffer_has_stencil_ ? 8 : 0);
5181 } else {
5182 glGetIntegerv(GL_STENCIL_BITS, &v);
5184 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5186 return true;
5187 case GL_COMPRESSED_TEXTURE_FORMATS:
5188 *num_written = validators_->compressed_texture_format.GetValues().size();
5189 if (params) {
5190 for (GLint ii = 0; ii < *num_written; ++ii) {
5191 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5194 return true;
5195 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5196 *num_written = 1;
5197 if (params) {
5198 *params = validators_->compressed_texture_format.GetValues().size();
5200 return true;
5201 case GL_NUM_SHADER_BINARY_FORMATS:
5202 *num_written = 1;
5203 if (params) {
5204 *params = validators_->shader_binary_format.GetValues().size();
5206 return true;
5207 case GL_SHADER_BINARY_FORMATS:
5208 *num_written = validators_->shader_binary_format.GetValues().size();
5209 if (params) {
5210 for (GLint ii = 0; ii < *num_written; ++ii) {
5211 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5214 return true;
5215 case GL_SHADER_COMPILER:
5216 *num_written = 1;
5217 if (params) {
5218 *params = GL_TRUE;
5220 return true;
5221 case GL_ARRAY_BUFFER_BINDING:
5222 *num_written = 1;
5223 if (params) {
5224 *params = GetClientId(
5225 buffer_manager(), state_.bound_array_buffer.get());
5227 return true;
5228 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5229 *num_written = 1;
5230 if (params) {
5231 *params = GetClientId(
5232 buffer_manager(),
5233 state_.vertex_attrib_manager->element_array_buffer());
5235 return true;
5236 case GL_COPY_READ_BUFFER_BINDING:
5237 *num_written = 1;
5238 if (params) {
5239 *params = GetClientId(
5240 buffer_manager(), state_.bound_copy_read_buffer.get());
5242 return true;
5243 case GL_COPY_WRITE_BUFFER_BINDING:
5244 *num_written = 1;
5245 if (params) {
5246 *params = GetClientId(
5247 buffer_manager(), state_.bound_copy_write_buffer.get());
5249 return true;
5250 case GL_PIXEL_PACK_BUFFER_BINDING:
5251 *num_written = 1;
5252 if (params) {
5253 *params = GetClientId(
5254 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5256 return true;
5257 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5258 *num_written = 1;
5259 if (params) {
5260 *params = GetClientId(
5261 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5263 return true;
5264 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5265 *num_written = 1;
5266 if (params) {
5267 *params = GetClientId(
5268 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5270 return true;
5271 case GL_UNIFORM_BUFFER_BINDING:
5272 *num_written = 1;
5273 if (params) {
5274 *params = GetClientId(
5275 buffer_manager(), state_.bound_uniform_buffer.get());
5277 return true;
5278 case GL_FRAMEBUFFER_BINDING:
5279 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5280 *num_written = 1;
5281 if (params) {
5282 *params = GetClientId(
5283 framebuffer_manager(),
5284 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5286 return true;
5287 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5288 *num_written = 1;
5289 if (params) {
5290 *params = GetClientId(
5291 framebuffer_manager(),
5292 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5294 return true;
5295 case GL_RENDERBUFFER_BINDING:
5296 *num_written = 1;
5297 if (params) {
5298 Renderbuffer* renderbuffer =
5299 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5300 if (renderbuffer) {
5301 *params = renderbuffer->client_id();
5302 } else {
5303 *params = 0;
5306 return true;
5307 case GL_CURRENT_PROGRAM:
5308 *num_written = 1;
5309 if (params) {
5310 *params = GetClientId(program_manager(), state_.current_program.get());
5312 return true;
5313 case GL_VERTEX_ARRAY_BINDING_OES:
5314 *num_written = 1;
5315 if (params) {
5316 if (state_.vertex_attrib_manager.get() !=
5317 state_.default_vertex_attrib_manager.get()) {
5318 GLuint client_id = 0;
5319 vertex_array_manager_->GetClientId(
5320 state_.vertex_attrib_manager->service_id(), &client_id);
5321 *params = client_id;
5322 } else {
5323 *params = 0;
5326 return true;
5327 case GL_TEXTURE_BINDING_2D:
5328 *num_written = 1;
5329 if (params) {
5330 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5331 if (unit.bound_texture_2d.get()) {
5332 *params = unit.bound_texture_2d->client_id();
5333 } else {
5334 *params = 0;
5337 return true;
5338 case GL_TEXTURE_BINDING_CUBE_MAP:
5339 *num_written = 1;
5340 if (params) {
5341 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5342 if (unit.bound_texture_cube_map.get()) {
5343 *params = unit.bound_texture_cube_map->client_id();
5344 } else {
5345 *params = 0;
5348 return true;
5349 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5350 *num_written = 1;
5351 if (params) {
5352 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5353 if (unit.bound_texture_external_oes.get()) {
5354 *params = unit.bound_texture_external_oes->client_id();
5355 } else {
5356 *params = 0;
5359 return true;
5360 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5361 *num_written = 1;
5362 if (params) {
5363 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5364 if (unit.bound_texture_rectangle_arb.get()) {
5365 *params = unit.bound_texture_rectangle_arb->client_id();
5366 } else {
5367 *params = 0;
5370 return true;
5371 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5372 *num_written = 1;
5373 if (params) {
5374 params[0] = group_->bind_generates_resource() ? 1 : 0;
5376 return true;
5377 default:
5378 if (pname >= GL_DRAW_BUFFER0_ARB &&
5379 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5380 *num_written = 1;
5381 if (params) {
5382 Framebuffer* framebuffer =
5383 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5384 if (framebuffer) {
5385 params[0] = framebuffer->GetDrawBuffer(pname);
5386 } else { // backbuffer
5387 if (pname == GL_DRAW_BUFFER0_ARB)
5388 params[0] = back_buffer_draw_buffer_;
5389 else
5390 params[0] = GL_NONE;
5393 return true;
5395 *num_written = util_.GLGetNumValuesReturned(pname);
5396 return false;
5400 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5401 GLenum pname, GLsizei* num_values) {
5402 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5403 return true;
5405 return GetHelper(pname, NULL, num_values);
5408 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5409 if (GL_MAX_SAMPLES == pname &&
5410 features().use_img_for_multisampled_render_to_texture) {
5411 return GL_MAX_SAMPLES_IMG;
5413 return pname;
5416 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5417 DCHECK(params);
5418 GLsizei num_written = 0;
5419 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5420 scoped_ptr<GLint[]> values(new GLint[num_written]);
5421 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5422 GetHelper(pname, values.get(), &num_written);
5424 for (GLsizei ii = 0; ii < num_written; ++ii) {
5425 params[ii] = static_cast<GLboolean>(values[ii]);
5427 } else {
5428 pname = AdjustGetPname(pname);
5429 glGetBooleanv(pname, params);
5433 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5434 DCHECK(params);
5435 GLsizei num_written = 0;
5436 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5437 if (GetHelper(pname, NULL, &num_written)) {
5438 scoped_ptr<GLint[]> values(new GLint[num_written]);
5439 GetHelper(pname, values.get(), &num_written);
5440 for (GLsizei ii = 0; ii < num_written; ++ii) {
5441 params[ii] = static_cast<GLfloat>(values[ii]);
5443 } else {
5444 pname = AdjustGetPname(pname);
5445 glGetFloatv(pname, params);
5450 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5451 DCHECK(params);
5452 if (unsafe_es3_apis_enabled()) {
5453 switch (pname) {
5454 case GL_MAX_ELEMENT_INDEX: {
5455 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5456 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5457 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5458 } else {
5459 // Assume that desktop GL implementations can generally support
5460 // 32-bit indices.
5461 if (params) {
5462 *params = std::numeric_limits<unsigned int>::max();
5465 return;
5469 pname = AdjustGetPname(pname);
5470 glGetInteger64v(pname, params);
5473 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5474 DCHECK(params);
5475 GLsizei num_written;
5476 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5477 !GetHelper(pname, params, &num_written)) {
5478 pname = AdjustGetPname(pname);
5479 glGetIntegerv(pname, params);
5483 void GLES2DecoderImpl::DoGetProgramiv(
5484 GLuint program_id, GLenum pname, GLint* params) {
5485 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5486 if (!program) {
5487 return;
5489 program->GetProgramiv(pname, params);
5492 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5493 GLenum target, GLenum pname, GLint64* params) {
5494 // Just delegate it. Some validation is actually done before this.
5495 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5496 &state_, target, pname, params);
5499 void GLES2DecoderImpl::DoGetBufferParameteriv(
5500 GLenum target, GLenum pname, GLint* params) {
5501 // Just delegate it. Some validation is actually done before this.
5502 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5503 &state_, target, pname, params);
5506 void GLES2DecoderImpl::DoBindAttribLocation(
5507 GLuint program_id, GLuint index, const char* name) {
5508 if (!StringIsValidForGLES(name)) {
5509 LOCAL_SET_GL_ERROR(
5510 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5511 return;
5513 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5514 LOCAL_SET_GL_ERROR(
5515 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5516 return;
5518 if (index >= group_->max_vertex_attribs()) {
5519 LOCAL_SET_GL_ERROR(
5520 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5521 return;
5523 Program* program = GetProgramInfoNotShader(
5524 program_id, "glBindAttribLocation");
5525 if (!program) {
5526 return;
5528 // At this point, the program's shaders may not be translated yet,
5529 // therefore, we may not find the hashed attribute name.
5530 // glBindAttribLocation call with original name is useless.
5531 // So instead, we should simply cache the binding, and then call
5532 // Program::ExecuteBindAttribLocationCalls() right before link.
5533 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5534 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5535 glBindAttribLocation(program->service_id(), index, name);
5538 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5539 uint32 immediate_data_size,
5540 const void* cmd_data) {
5541 const gles2::cmds::BindAttribLocationBucket& c =
5542 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5543 GLuint program = static_cast<GLuint>(c.program);
5544 GLuint index = static_cast<GLuint>(c.index);
5545 Bucket* bucket = GetBucket(c.name_bucket_id);
5546 if (!bucket || bucket->size() == 0) {
5547 return error::kInvalidArguments;
5549 std::string name_str;
5550 if (!bucket->GetAsString(&name_str)) {
5551 return error::kInvalidArguments;
5553 DoBindAttribLocation(program, index, name_str.c_str());
5554 return error::kNoError;
5557 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5558 GLuint program_id, GLint location, const char* name) {
5559 if (!StringIsValidForGLES(name)) {
5560 LOCAL_SET_GL_ERROR(
5561 GL_INVALID_VALUE,
5562 "glBindUniformLocationCHROMIUM", "Invalid character");
5563 return;
5565 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5566 LOCAL_SET_GL_ERROR(
5567 GL_INVALID_OPERATION,
5568 "glBindUniformLocationCHROMIUM", "reserved prefix");
5569 return;
5571 if (location < 0 || static_cast<uint32>(location) >=
5572 (group_->max_fragment_uniform_vectors() +
5573 group_->max_vertex_uniform_vectors()) * 4) {
5574 LOCAL_SET_GL_ERROR(
5575 GL_INVALID_VALUE,
5576 "glBindUniformLocationCHROMIUM", "location out of range");
5577 return;
5579 Program* program = GetProgramInfoNotShader(
5580 program_id, "glBindUniformLocationCHROMIUM");
5581 if (!program) {
5582 return;
5584 if (!program->SetUniformLocationBinding(name, location)) {
5585 LOCAL_SET_GL_ERROR(
5586 GL_INVALID_VALUE,
5587 "glBindUniformLocationCHROMIUM", "location out of range");
5591 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5592 uint32 immediate_data_size,
5593 const void* cmd_data) {
5594 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5595 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5596 cmd_data);
5597 GLuint program = static_cast<GLuint>(c.program);
5598 GLint location = static_cast<GLint>(c.location);
5599 Bucket* bucket = GetBucket(c.name_bucket_id);
5600 if (!bucket || bucket->size() == 0) {
5601 return error::kInvalidArguments;
5603 std::string name_str;
5604 if (!bucket->GetAsString(&name_str)) {
5605 return error::kInvalidArguments;
5607 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5608 return error::kNoError;
5611 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5612 const void* cmd_data) {
5613 const gles2::cmds::DeleteShader& c =
5614 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5615 GLuint client_id = c.shader;
5616 if (client_id) {
5617 Shader* shader = GetShader(client_id);
5618 if (shader) {
5619 if (!shader->IsDeleted()) {
5620 shader_manager()->Delete(shader);
5622 } else {
5623 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5626 return error::kNoError;
5629 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5630 const void* cmd_data) {
5631 const gles2::cmds::DeleteProgram& c =
5632 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5633 GLuint client_id = c.program;
5634 if (client_id) {
5635 Program* program = GetProgram(client_id);
5636 if (program) {
5637 if (!program->IsDeleted()) {
5638 program_manager()->MarkAsDeleted(shader_manager(), program);
5640 } else {
5641 LOCAL_SET_GL_ERROR(
5642 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5645 return error::kNoError;
5648 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5649 DCHECK(!ShouldDeferDraws());
5650 if (CheckBoundFramebuffersValid("glClear")) {
5651 ApplyDirtyState();
5652 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5653 if (workarounds().gl_clear_broken) {
5654 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5655 GetErrorState());
5656 if (!BoundFramebufferHasDepthAttachment())
5657 mask &= ~GL_DEPTH_BUFFER_BIT;
5658 if (!BoundFramebufferHasStencilAttachment())
5659 mask &= ~GL_STENCIL_BUFFER_BIT;
5660 clear_framebuffer_blit_->ClearFramebuffer(
5661 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5662 state_.color_clear_green, state_.color_clear_blue,
5663 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5664 return error::kNoError;
5666 glClear(mask);
5668 return error::kNoError;
5671 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5672 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5673 GLuint client_renderbuffer_id) {
5674 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5675 if (!framebuffer) {
5676 LOCAL_SET_GL_ERROR(
5677 GL_INVALID_OPERATION,
5678 "glFramebufferRenderbuffer", "no framebuffer bound");
5679 return;
5681 GLuint service_id = 0;
5682 Renderbuffer* renderbuffer = NULL;
5683 if (client_renderbuffer_id) {
5684 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5685 if (!renderbuffer) {
5686 LOCAL_SET_GL_ERROR(
5687 GL_INVALID_OPERATION,
5688 "glFramebufferRenderbuffer", "unknown renderbuffer");
5689 return;
5691 service_id = renderbuffer->service_id();
5693 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5694 glFramebufferRenderbufferEXT(
5695 target, attachment, renderbuffertarget, service_id);
5696 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5697 if (error == GL_NO_ERROR) {
5698 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5700 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5701 framebuffer_state_.clear_state_dirty = true;
5703 OnFboChanged();
5706 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5707 if (SetCapabilityState(cap, false)) {
5708 glDisable(cap);
5712 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5713 if (SetCapabilityState(cap, true)) {
5714 glEnable(cap);
5718 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5719 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5720 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5721 glDepthRange(znear, zfar);
5724 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5725 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5726 state_.sample_coverage_invert = (invert != 0);
5727 glSampleCoverage(state_.sample_coverage_value, invert);
5730 // Assumes framebuffer is complete.
5731 void GLES2DecoderImpl::ClearUnclearedAttachments(
5732 GLenum target, Framebuffer* framebuffer) {
5733 if (target == GL_READ_FRAMEBUFFER_EXT) {
5734 // bind this to the DRAW point, clear then bind back to READ
5735 // TODO(gman): I don't think there is any guarantee that an FBO that
5736 // is complete on the READ attachment will be complete as a DRAW
5737 // attachment.
5738 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5739 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5741 GLbitfield clear_bits = 0;
5742 if (framebuffer->HasUnclearedColorAttachments()) {
5743 // We should always use alpha == 0 here, because 1) some draw buffers may
5744 // have alpha and some may not; 2) we won't have the same situation as the
5745 // back buffer where alpha channel exists but is not requested.
5746 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
5747 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5748 clear_bits |= GL_COLOR_BUFFER_BIT;
5749 if (feature_info_->feature_flags().ext_draw_buffers)
5750 framebuffer->PrepareDrawBuffersForClear();
5753 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5754 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5755 glClearStencil(0);
5756 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5757 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5758 clear_bits |= GL_STENCIL_BUFFER_BIT;
5761 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5762 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5763 glClearDepth(1.0f);
5764 state_.SetDeviceDepthMask(GL_TRUE);
5765 clear_bits |= GL_DEPTH_BUFFER_BIT;
5768 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5769 glClear(clear_bits);
5771 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5772 feature_info_->feature_flags().ext_draw_buffers)
5773 framebuffer->RestoreDrawBuffersAfterClear();
5775 framebuffer_manager()->MarkAttachmentsAsCleared(
5776 framebuffer, renderbuffer_manager(), texture_manager());
5778 RestoreClearState();
5780 if (target == GL_READ_FRAMEBUFFER_EXT) {
5781 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5782 Framebuffer* draw_framebuffer =
5783 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5784 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5785 GetBackbufferServiceId();
5786 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5790 void GLES2DecoderImpl::RestoreClearState() {
5791 framebuffer_state_.clear_state_dirty = true;
5792 glClearColor(
5793 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5794 state_.color_clear_alpha);
5795 glClearStencil(state_.stencil_clear);
5796 glClearDepth(state_.depth_clear);
5797 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5798 state_.enable_flags.scissor_test);
5799 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
5800 state_.scissor_height);
5803 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5804 Framebuffer* framebuffer =
5805 GetFramebufferInfoForTarget(target);
5806 if (!framebuffer) {
5807 return GL_FRAMEBUFFER_COMPLETE;
5809 GLenum completeness = framebuffer->IsPossiblyComplete();
5810 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5811 return completeness;
5813 return framebuffer->GetStatus(texture_manager(), target);
5816 void GLES2DecoderImpl::DoFramebufferTexture2D(
5817 GLenum target, GLenum attachment, GLenum textarget,
5818 GLuint client_texture_id, GLint level) {
5819 DoFramebufferTexture2DCommon(
5820 "glFramebufferTexture2D", target, attachment,
5821 textarget, client_texture_id, level, 0);
5824 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5825 GLenum target, GLenum attachment, GLenum textarget,
5826 GLuint client_texture_id, GLint level, GLsizei samples) {
5827 DoFramebufferTexture2DCommon(
5828 "glFramebufferTexture2DMultisample", target, attachment,
5829 textarget, client_texture_id, level, samples);
5832 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5833 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5834 GLuint client_texture_id, GLint level, GLsizei samples) {
5835 if (samples > renderbuffer_manager()->max_samples()) {
5836 LOCAL_SET_GL_ERROR(
5837 GL_INVALID_VALUE,
5838 "glFramebufferTexture2DMultisample", "samples too large");
5839 return;
5841 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5842 if (!framebuffer) {
5843 LOCAL_SET_GL_ERROR(
5844 GL_INVALID_OPERATION,
5845 name, "no framebuffer bound.");
5846 return;
5848 GLuint service_id = 0;
5849 TextureRef* texture_ref = NULL;
5850 if (client_texture_id) {
5851 texture_ref = GetTexture(client_texture_id);
5852 if (!texture_ref) {
5853 LOCAL_SET_GL_ERROR(
5854 GL_INVALID_OPERATION,
5855 name, "unknown texture_ref");
5856 return;
5858 service_id = texture_ref->service_id();
5861 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5862 LOCAL_SET_GL_ERROR(
5863 GL_INVALID_VALUE,
5864 name, "level out of range");
5865 return;
5868 if (texture_ref)
5869 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5871 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5872 if (0 == samples) {
5873 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5874 } else {
5875 if (features().use_img_for_multisampled_render_to_texture) {
5876 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5877 service_id, level, samples);
5878 } else {
5879 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5880 service_id, level, samples);
5883 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5884 if (error == GL_NO_ERROR) {
5885 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5886 samples);
5888 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5889 framebuffer_state_.clear_state_dirty = true;
5892 if (texture_ref)
5893 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5895 OnFboChanged();
5898 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5899 GLenum target, GLenum attachment, GLuint client_texture_id,
5900 GLint level, GLint layer) {
5901 // TODO(zmo): Unsafe ES3 API, missing states update.
5902 GLuint service_id = 0;
5903 TextureRef* texture_ref = NULL;
5904 if (client_texture_id) {
5905 texture_ref = GetTexture(client_texture_id);
5906 if (!texture_ref) {
5907 LOCAL_SET_GL_ERROR(
5908 GL_INVALID_OPERATION,
5909 "glFramebufferTextureLayer", "unknown texture_ref");
5910 return;
5912 service_id = texture_ref->service_id();
5914 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5917 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5918 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5919 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5920 if (!framebuffer) {
5921 LOCAL_SET_GL_ERROR(
5922 GL_INVALID_OPERATION,
5923 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5924 return;
5926 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5927 const Framebuffer::Attachment* attachment_object =
5928 framebuffer->GetAttachment(attachment);
5929 *params = attachment_object ? attachment_object->object_name() : 0;
5930 } else {
5931 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5932 features().use_img_for_multisampled_render_to_texture) {
5933 pname = GL_TEXTURE_SAMPLES_IMG;
5935 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5939 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5940 GLenum target, GLenum pname, GLint* params) {
5941 Renderbuffer* renderbuffer =
5942 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5943 if (!renderbuffer) {
5944 LOCAL_SET_GL_ERROR(
5945 GL_INVALID_OPERATION,
5946 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5947 return;
5950 EnsureRenderbufferBound();
5951 switch (pname) {
5952 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5953 *params = renderbuffer->internal_format();
5954 break;
5955 case GL_RENDERBUFFER_WIDTH:
5956 *params = renderbuffer->width();
5957 break;
5958 case GL_RENDERBUFFER_HEIGHT:
5959 *params = renderbuffer->height();
5960 break;
5961 case GL_RENDERBUFFER_SAMPLES_EXT:
5962 if (features().use_img_for_multisampled_render_to_texture) {
5963 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5964 params);
5965 } else {
5966 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5967 params);
5969 default:
5970 glGetRenderbufferParameterivEXT(target, pname, params);
5971 break;
5975 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5976 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5977 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5978 GLbitfield mask, GLenum filter) {
5979 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5981 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5982 return;
5985 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5986 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5987 BlitFramebufferHelper(
5988 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5989 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5990 state_.enable_flags.scissor_test);
5993 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5994 if (!state_.bound_renderbuffer_valid) {
5995 state_.bound_renderbuffer_valid = true;
5996 glBindRenderbufferEXT(GL_RENDERBUFFER,
5997 state_.bound_renderbuffer.get()
5998 ? state_.bound_renderbuffer->service_id()
5999 : 0);
6003 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6004 const FeatureInfo* feature_info,
6005 GLenum target,
6006 GLsizei samples,
6007 GLenum internal_format,
6008 GLsizei width,
6009 GLsizei height) {
6010 // TODO(sievers): This could be resolved at the GL binding level, but the
6011 // binding process is currently a bit too 'brute force'.
6012 if (feature_info->gl_version_info().is_angle) {
6013 glRenderbufferStorageMultisampleANGLE(
6014 target, samples, internal_format, width, height);
6015 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6016 glRenderbufferStorageMultisample(
6017 target, samples, internal_format, width, height);
6018 } else {
6019 glRenderbufferStorageMultisampleEXT(
6020 target, samples, internal_format, width, height);
6024 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6025 GLint srcY0,
6026 GLint srcX1,
6027 GLint srcY1,
6028 GLint dstX0,
6029 GLint dstY0,
6030 GLint dstX1,
6031 GLint dstY1,
6032 GLbitfield mask,
6033 GLenum filter) {
6034 // TODO(sievers): This could be resolved at the GL binding level, but the
6035 // binding process is currently a bit too 'brute force'.
6036 if (feature_info_->gl_version_info().is_angle) {
6037 glBlitFramebufferANGLE(
6038 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6039 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6040 glBlitFramebuffer(
6041 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6042 } else {
6043 glBlitFramebufferEXT(
6044 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6048 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6049 GLsizei samples,
6050 GLenum internalformat,
6051 GLsizei width,
6052 GLsizei height) {
6053 if (samples > renderbuffer_manager()->max_samples()) {
6054 LOCAL_SET_GL_ERROR(
6055 GL_INVALID_VALUE,
6056 "glRenderbufferStorageMultisample", "samples too large");
6057 return false;
6060 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6061 height > renderbuffer_manager()->max_renderbuffer_size()) {
6062 LOCAL_SET_GL_ERROR(
6063 GL_INVALID_VALUE,
6064 "glRenderbufferStorageMultisample", "dimensions too large");
6065 return false;
6068 uint32 estimated_size = 0;
6069 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6070 width, height, samples, internalformat, &estimated_size)) {
6071 LOCAL_SET_GL_ERROR(
6072 GL_OUT_OF_MEMORY,
6073 "glRenderbufferStorageMultisample", "dimensions too large");
6074 return false;
6077 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6078 LOCAL_SET_GL_ERROR(
6079 GL_OUT_OF_MEMORY,
6080 "glRenderbufferStorageMultisample", "out of memory");
6081 return false;
6084 return true;
6087 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6088 GLenum target, GLsizei samples, GLenum internalformat,
6089 GLsizei width, GLsizei height) {
6090 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6091 if (!renderbuffer) {
6092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6093 "glRenderbufferStorageMultisampleCHROMIUM",
6094 "no renderbuffer bound");
6095 return;
6098 if (!ValidateRenderbufferStorageMultisample(
6099 samples, internalformat, width, height)) {
6100 return;
6103 EnsureRenderbufferBound();
6104 GLenum impl_format =
6105 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6106 internalformat);
6107 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6108 "glRenderbufferStorageMultisampleCHROMIUM");
6109 RenderbufferStorageMultisampleHelper(
6110 feature_info_.get(), target, samples, impl_format, width, height);
6111 GLenum error =
6112 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6113 if (error == GL_NO_ERROR) {
6114 if (workarounds().validate_multisample_buffer_allocation) {
6115 if (!VerifyMultisampleRenderbufferIntegrity(
6116 renderbuffer->service_id(), impl_format)) {
6117 LOCAL_SET_GL_ERROR(
6118 GL_OUT_OF_MEMORY,
6119 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6120 return;
6124 // TODO(gman): If renderbuffers tracked which framebuffers they were
6125 // attached to we could just mark those framebuffers as not complete.
6126 framebuffer_manager()->IncFramebufferStateChangeCount();
6127 renderbuffer_manager()->SetInfo(
6128 renderbuffer, samples, internalformat, width, height);
6132 // This is the handler for multisampled_render_to_texture extensions.
6133 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6134 GLenum target, GLsizei samples, GLenum internalformat,
6135 GLsizei width, GLsizei height) {
6136 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6137 if (!renderbuffer) {
6138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6139 "glRenderbufferStorageMultisampleEXT",
6140 "no renderbuffer bound");
6141 return;
6144 if (!ValidateRenderbufferStorageMultisample(
6145 samples, internalformat, width, height)) {
6146 return;
6149 EnsureRenderbufferBound();
6150 GLenum impl_format =
6151 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6152 internalformat);
6153 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6154 if (features().use_img_for_multisampled_render_to_texture) {
6155 glRenderbufferStorageMultisampleIMG(
6156 target, samples, impl_format, width, height);
6157 } else {
6158 glRenderbufferStorageMultisampleEXT(
6159 target, samples, impl_format, width, height);
6161 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6162 if (error == GL_NO_ERROR) {
6163 // TODO(gman): If renderbuffers tracked which framebuffers they were
6164 // attached to we could just mark those framebuffers as not complete.
6165 framebuffer_manager()->IncFramebufferStateChangeCount();
6166 renderbuffer_manager()->SetInfo(
6167 renderbuffer, samples, internalformat, width, height);
6171 // This function validates the allocation of a multisampled renderbuffer
6172 // by clearing it to a key color, blitting the contents to a texture, and
6173 // reading back the color to ensure it matches the key.
6174 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6175 GLuint renderbuffer, GLenum format) {
6177 // Only validate color buffers.
6178 // These formats have been selected because they are very common or are known
6179 // to be used by the WebGL backbuffer. If problems are observed with other
6180 // color formats they can be added here.
6181 switch (format) {
6182 case GL_RGB:
6183 case GL_RGB8:
6184 case GL_RGBA:
6185 case GL_RGBA8:
6186 break;
6187 default:
6188 return true;
6191 GLint draw_framebuffer, read_framebuffer;
6193 // Cache framebuffer and texture bindings.
6194 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6195 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6197 if (!validation_texture_) {
6198 GLint bound_texture;
6199 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6201 // Create additional resources needed for the verification.
6202 glGenTextures(1, &validation_texture_);
6203 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6204 glGenFramebuffersEXT(1, &validation_fbo_);
6206 // Texture only needs to be 1x1.
6207 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6208 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6209 // multisample will fail if the color format of the source and destination
6210 // do not match. Here, we assume that the source is GL_RGBA, and make the
6211 // destination GL_RGBA. http://crbug.com/484203
6212 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6213 GL_UNSIGNED_BYTE, NULL);
6215 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6216 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6217 GL_TEXTURE_2D, validation_texture_, 0);
6219 glBindTexture(GL_TEXTURE_2D, bound_texture);
6222 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6223 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6224 GL_RENDERBUFFER, renderbuffer);
6226 // Cache current state and reset it to the values we require.
6227 GLboolean scissor_enabled = false;
6228 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6229 if (scissor_enabled)
6230 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6232 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6233 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6234 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6236 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6237 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6238 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6240 // Clear the buffer to the desired key color.
6241 glClear(GL_COLOR_BUFFER_BIT);
6243 // Blit from the multisample buffer to a standard texture.
6244 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6245 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6247 BlitFramebufferHelper(
6248 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6250 // Read a pixel from the buffer.
6251 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6253 unsigned char pixel[3] = {0, 0, 0};
6254 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6256 // Detach the renderbuffer.
6257 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6258 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6259 GL_RENDERBUFFER, 0);
6261 // Restore cached state.
6262 if (scissor_enabled)
6263 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6265 state_.SetDeviceColorMask(
6266 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6267 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6268 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6269 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6271 // Return true if the pixel matched the desired key color.
6272 return (pixel[0] == 0xFF &&
6273 pixel[1] == 0x00 &&
6274 pixel[2] == 0xFF);
6277 void GLES2DecoderImpl::DoRenderbufferStorage(
6278 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6279 Renderbuffer* renderbuffer =
6280 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6281 if (!renderbuffer) {
6282 LOCAL_SET_GL_ERROR(
6283 GL_INVALID_OPERATION,
6284 "glRenderbufferStorage", "no renderbuffer bound");
6285 return;
6288 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6289 height > renderbuffer_manager()->max_renderbuffer_size()) {
6290 LOCAL_SET_GL_ERROR(
6291 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6292 return;
6295 uint32 estimated_size = 0;
6296 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6297 width, height, 1, internalformat, &estimated_size)) {
6298 LOCAL_SET_GL_ERROR(
6299 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6300 return;
6303 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6304 LOCAL_SET_GL_ERROR(
6305 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6306 return;
6309 EnsureRenderbufferBound();
6310 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6311 glRenderbufferStorageEXT(
6312 target,
6313 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6314 internalformat),
6315 width,
6316 height);
6317 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6318 if (error == GL_NO_ERROR) {
6319 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6320 // we could just mark those framebuffers as not complete.
6321 framebuffer_manager()->IncFramebufferStateChangeCount();
6322 renderbuffer_manager()->SetInfo(
6323 renderbuffer, 1, internalformat, width, height);
6327 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6328 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6329 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6330 Program* program = GetProgramInfoNotShader(
6331 program_id, "glLinkProgram");
6332 if (!program) {
6333 return;
6336 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6337 if (program->Link(shader_manager(),
6338 workarounds().count_all_in_varyings_packing ?
6339 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6340 shader_cache_callback_)) {
6341 if (program == state_.current_program.get()) {
6342 if (workarounds().use_current_program_after_successful_link)
6343 glUseProgram(program->service_id());
6344 if (workarounds().clear_uniforms_before_first_program_use)
6345 program_manager()->ClearUniforms(program);
6349 // LinkProgram can be very slow. Exit command processing to allow for
6350 // context preemption and GPU watchdog checks.
6351 ExitCommandProcessingEarly();
6354 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6355 switch (src) {
6356 case GL_NONE:
6357 case GL_BACK:
6358 break;
6359 default:
6361 GLenum upper_limit = static_cast<GLenum>(
6362 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6363 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6364 LOCAL_SET_GL_ERROR(
6365 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6366 return;
6369 break;
6372 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6373 if (framebuffer) {
6374 if (src == GL_BACK) {
6375 LOCAL_SET_GL_ERROR(
6376 GL_INVALID_ENUM, "glReadBuffer",
6377 "invalid src for a named framebuffer");
6378 return;
6380 framebuffer->set_read_buffer(src);
6381 } else {
6382 if (src != GL_NONE && src != GL_BACK) {
6383 LOCAL_SET_GL_ERROR(
6384 GL_INVALID_ENUM, "glReadBuffer",
6385 "invalid src for the default framebuffer");
6386 return;
6388 back_buffer_read_buffer_ = src;
6389 if (GetBackbufferServiceId() && src == GL_BACK)
6390 src = GL_COLOR_ATTACHMENT0;
6392 glReadBuffer(src);
6395 void GLES2DecoderImpl::DoSamplerParameterfv(
6396 GLuint sampler, GLenum pname, const GLfloat* params) {
6397 DCHECK(params);
6398 glSamplerParameterf(sampler, pname, params[0]);
6401 void GLES2DecoderImpl::DoSamplerParameteriv(
6402 GLuint sampler, GLenum pname, const GLint* params) {
6403 DCHECK(params);
6404 glSamplerParameteri(sampler, pname, params[0]);
6407 void GLES2DecoderImpl::DoTexParameterf(
6408 GLenum target, GLenum pname, GLfloat param) {
6409 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6410 &state_, target);
6411 if (!texture) {
6412 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6413 return;
6416 texture_manager()->SetParameterf(
6417 "glTexParameterf", GetErrorState(), texture, pname, param);
6420 void GLES2DecoderImpl::DoTexParameteri(
6421 GLenum target, GLenum pname, GLint param) {
6422 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6423 &state_, target);
6424 if (!texture) {
6425 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6426 return;
6429 texture_manager()->SetParameteri(
6430 "glTexParameteri", GetErrorState(), texture, pname, param);
6433 void GLES2DecoderImpl::DoTexParameterfv(
6434 GLenum target, GLenum pname, const GLfloat* params) {
6435 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6436 &state_, target);
6437 if (!texture) {
6438 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6439 return;
6442 texture_manager()->SetParameterf(
6443 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6446 void GLES2DecoderImpl::DoTexParameteriv(
6447 GLenum target, GLenum pname, const GLint* params) {
6448 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6449 &state_, target);
6450 if (!texture) {
6451 LOCAL_SET_GL_ERROR(
6452 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6453 return;
6456 texture_manager()->SetParameteri(
6457 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6460 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6461 if (!state_.bound_valuebuffer.get()) {
6462 // There is no valuebuffer bound
6463 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6464 "no valuebuffer in use");
6465 return false;
6467 return true;
6470 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6471 GLenum subscription,
6472 const char* function_name) {
6473 if (!CheckCurrentValuebuffer(function_name)) {
6474 return false;
6476 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6477 // The valuebuffer is not subscribed to the target
6478 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6479 "valuebuffer is not subscribed");
6480 return false;
6482 return true;
6485 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6486 GLenum subscription,
6487 const char* function_name) {
6488 if (!CheckCurrentProgramForUniform(location, function_name)) {
6489 return false;
6491 GLint real_location = -1;
6492 GLint array_index = -1;
6493 const Program::UniformInfo* info =
6494 state_.current_program->GetUniformInfoByFakeLocation(
6495 location, &real_location, &array_index);
6496 if (!info) {
6497 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6498 return false;
6500 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6501 info->accepts_api_type) == 0) {
6502 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6503 "wrong type for subscription");
6504 return false;
6506 return true;
6509 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6510 if (!state_.current_program.get()) {
6511 // The program does not exist.
6512 LOCAL_SET_GL_ERROR(
6513 GL_INVALID_OPERATION, function_name, "no program in use");
6514 return false;
6516 if (!state_.current_program->InUse()) {
6517 LOCAL_SET_GL_ERROR(
6518 GL_INVALID_OPERATION, function_name, "program not linked");
6519 return false;
6521 return true;
6524 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6525 GLint location, const char* function_name) {
6526 if (!CheckCurrentProgram(function_name)) {
6527 return false;
6529 return location != -1;
6532 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6533 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6534 if (!framebuffer)
6535 return false;
6536 const Framebuffer::Attachment* attachment =
6537 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6538 if (!attachment)
6539 return false;
6541 DCHECK(state_.current_program.get());
6542 const Program::SamplerIndices& sampler_indices =
6543 state_.current_program->sampler_indices();
6544 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6545 const Program::UniformInfo* uniform_info =
6546 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6547 DCHECK(uniform_info);
6548 if (uniform_info->type != GL_SAMPLER_2D)
6549 continue;
6550 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6551 GLuint texture_unit_index = uniform_info->texture_units[jj];
6552 if (texture_unit_index >= state_.texture_units.size())
6553 continue;
6554 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6555 TextureRef* texture_ref =
6556 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6557 if (attachment->IsTexture(texture_ref))
6558 return true;
6561 return false;
6564 bool GLES2DecoderImpl::CheckUniformForApiType(
6565 const Program::UniformInfo* info,
6566 const char* function_name,
6567 Program::UniformApiType api_type) {
6568 DCHECK(info);
6569 if ((api_type & info->accepts_api_type) == 0) {
6570 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6571 "wrong uniform function for type");
6572 return false;
6574 return true;
6577 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6578 GLint fake_location,
6579 const char* function_name,
6580 Program::UniformApiType api_type,
6581 GLint* real_location,
6582 GLenum* type,
6583 GLsizei* count) {
6584 DCHECK(type);
6585 DCHECK(count);
6586 DCHECK(real_location);
6588 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6589 return false;
6591 GLint array_index = -1;
6592 const Program::UniformInfo* info =
6593 state_.current_program->GetUniformInfoByFakeLocation(
6594 fake_location, real_location, &array_index);
6595 if (!info) {
6596 LOCAL_SET_GL_ERROR(
6597 GL_INVALID_OPERATION, function_name, "unknown location");
6598 return false;
6600 if (!CheckUniformForApiType(info, function_name, api_type)) {
6601 return false;
6603 if (*count > 1 && !info->is_array) {
6604 LOCAL_SET_GL_ERROR(
6605 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6606 return false;
6608 *count = std::min(info->size - array_index, *count);
6609 if (*count <= 0) {
6610 return false;
6612 *type = info->type;
6613 return true;
6616 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6617 GLenum type = 0;
6618 GLsizei count = 1;
6619 GLint real_location = -1;
6620 if (!PrepForSetUniformByLocation(fake_location,
6621 "glUniform1i",
6622 Program::kUniform1i,
6623 &real_location,
6624 &type,
6625 &count)) {
6626 return;
6628 if (!state_.current_program->SetSamplers(
6629 state_.texture_units.size(), fake_location, 1, &v0)) {
6630 LOCAL_SET_GL_ERROR(
6631 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6632 return;
6634 glUniform1i(real_location, v0);
6637 void GLES2DecoderImpl::DoUniform1iv(
6638 GLint fake_location, GLsizei count, const GLint *value) {
6639 GLenum type = 0;
6640 GLint real_location = -1;
6641 if (!PrepForSetUniformByLocation(fake_location,
6642 "glUniform1iv",
6643 Program::kUniform1i,
6644 &real_location,
6645 &type,
6646 &count)) {
6647 return;
6649 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6650 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6651 if (!state_.current_program->SetSamplers(
6652 state_.texture_units.size(), fake_location, count, value)) {
6653 LOCAL_SET_GL_ERROR(
6654 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6655 return;
6658 glUniform1iv(real_location, count, value);
6661 void GLES2DecoderImpl::DoUniform1fv(
6662 GLint fake_location, GLsizei count, const GLfloat* value) {
6663 GLenum type = 0;
6664 GLint real_location = -1;
6665 if (!PrepForSetUniformByLocation(fake_location,
6666 "glUniform1fv",
6667 Program::kUniform1f,
6668 &real_location,
6669 &type,
6670 &count)) {
6671 return;
6673 if (type == GL_BOOL) {
6674 scoped_ptr<GLint[]> temp(new GLint[count]);
6675 for (GLsizei ii = 0; ii < count; ++ii) {
6676 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6678 DoUniform1iv(real_location, count, temp.get());
6679 } else {
6680 glUniform1fv(real_location, count, value);
6684 void GLES2DecoderImpl::DoUniform2fv(
6685 GLint fake_location, GLsizei count, const GLfloat* value) {
6686 GLenum type = 0;
6687 GLint real_location = -1;
6688 if (!PrepForSetUniformByLocation(fake_location,
6689 "glUniform2fv",
6690 Program::kUniform2f,
6691 &real_location,
6692 &type,
6693 &count)) {
6694 return;
6696 if (type == GL_BOOL_VEC2) {
6697 GLsizei num_values = count * 2;
6698 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6699 for (GLsizei ii = 0; ii < num_values; ++ii) {
6700 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6702 glUniform2iv(real_location, count, temp.get());
6703 } else {
6704 glUniform2fv(real_location, count, value);
6708 void GLES2DecoderImpl::DoUniform3fv(
6709 GLint fake_location, GLsizei count, const GLfloat* value) {
6710 GLenum type = 0;
6711 GLint real_location = -1;
6712 if (!PrepForSetUniformByLocation(fake_location,
6713 "glUniform3fv",
6714 Program::kUniform3f,
6715 &real_location,
6716 &type,
6717 &count)) {
6718 return;
6720 if (type == GL_BOOL_VEC3) {
6721 GLsizei num_values = count * 3;
6722 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6723 for (GLsizei ii = 0; ii < num_values; ++ii) {
6724 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6726 glUniform3iv(real_location, count, temp.get());
6727 } else {
6728 glUniform3fv(real_location, count, value);
6732 void GLES2DecoderImpl::DoUniform4fv(
6733 GLint fake_location, GLsizei count, const GLfloat* value) {
6734 GLenum type = 0;
6735 GLint real_location = -1;
6736 if (!PrepForSetUniformByLocation(fake_location,
6737 "glUniform4fv",
6738 Program::kUniform4f,
6739 &real_location,
6740 &type,
6741 &count)) {
6742 return;
6744 if (type == GL_BOOL_VEC4) {
6745 GLsizei num_values = count * 4;
6746 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6747 for (GLsizei ii = 0; ii < num_values; ++ii) {
6748 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6750 glUniform4iv(real_location, count, temp.get());
6751 } else {
6752 glUniform4fv(real_location, count, value);
6756 void GLES2DecoderImpl::DoUniform2iv(
6757 GLint fake_location, GLsizei count, const GLint* value) {
6758 GLenum type = 0;
6759 GLint real_location = -1;
6760 if (!PrepForSetUniformByLocation(fake_location,
6761 "glUniform2iv",
6762 Program::kUniform2i,
6763 &real_location,
6764 &type,
6765 &count)) {
6766 return;
6768 glUniform2iv(real_location, count, value);
6771 void GLES2DecoderImpl::DoUniform3iv(
6772 GLint fake_location, GLsizei count, const GLint* value) {
6773 GLenum type = 0;
6774 GLint real_location = -1;
6775 if (!PrepForSetUniformByLocation(fake_location,
6776 "glUniform3iv",
6777 Program::kUniform3i,
6778 &real_location,
6779 &type,
6780 &count)) {
6781 return;
6783 glUniform3iv(real_location, count, value);
6786 void GLES2DecoderImpl::DoUniform4iv(
6787 GLint fake_location, GLsizei count, const GLint* value) {
6788 GLenum type = 0;
6789 GLint real_location = -1;
6790 if (!PrepForSetUniformByLocation(fake_location,
6791 "glUniform4iv",
6792 Program::kUniform4i,
6793 &real_location,
6794 &type,
6795 &count)) {
6796 return;
6798 glUniform4iv(real_location, count, value);
6801 void GLES2DecoderImpl::DoUniformMatrix2fv(
6802 GLint fake_location, GLsizei count, GLboolean transpose,
6803 const GLfloat* value) {
6804 GLenum type = 0;
6805 GLint real_location = -1;
6806 if (!PrepForSetUniformByLocation(fake_location,
6807 "glUniformMatrix2fv",
6808 Program::kUniformMatrix2f,
6809 &real_location,
6810 &type,
6811 &count)) {
6812 return;
6814 glUniformMatrix2fv(real_location, count, transpose, value);
6817 void GLES2DecoderImpl::DoUniformMatrix3fv(
6818 GLint fake_location, GLsizei count, GLboolean transpose,
6819 const GLfloat* value) {
6820 GLenum type = 0;
6821 GLint real_location = -1;
6822 if (!PrepForSetUniformByLocation(fake_location,
6823 "glUniformMatrix3fv",
6824 Program::kUniformMatrix3f,
6825 &real_location,
6826 &type,
6827 &count)) {
6828 return;
6830 glUniformMatrix3fv(real_location, count, transpose, value);
6833 void GLES2DecoderImpl::DoUniformMatrix4fv(
6834 GLint fake_location, GLsizei count, GLboolean transpose,
6835 const GLfloat* value) {
6836 GLenum type = 0;
6837 GLint real_location = -1;
6838 if (!PrepForSetUniformByLocation(fake_location,
6839 "glUniformMatrix4fv",
6840 Program::kUniformMatrix4f,
6841 &real_location,
6842 &type,
6843 &count)) {
6844 return;
6846 glUniformMatrix4fv(real_location, count, transpose, value);
6849 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6850 GLuint service_id = 0;
6851 Program* program = NULL;
6852 if (program_id) {
6853 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6854 if (!program) {
6855 return;
6857 if (!program->IsValid()) {
6858 // Program was not linked successfully. (ie, glLinkProgram)
6859 LOCAL_SET_GL_ERROR(
6860 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6861 return;
6863 service_id = program->service_id();
6865 if (state_.current_program.get()) {
6866 program_manager()->UnuseProgram(shader_manager(),
6867 state_.current_program.get());
6869 state_.current_program = program;
6870 LogClientServiceMapping("glUseProgram", program_id, service_id);
6871 glUseProgram(service_id);
6872 if (state_.current_program.get()) {
6873 program_manager()->UseProgram(state_.current_program.get());
6874 if (workarounds().clear_uniforms_before_first_program_use)
6875 program_manager()->ClearUniforms(program);
6879 void GLES2DecoderImpl::RenderWarning(
6880 const char* filename, int line, const std::string& msg) {
6881 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6884 void GLES2DecoderImpl::PerformanceWarning(
6885 const char* filename, int line, const std::string& msg) {
6886 logger_.LogMessage(filename, line,
6887 std::string("PERFORMANCE WARNING: ") + msg);
6890 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6891 Texture* texture, GLenum textarget) {
6892 // Image is already in use if texture is attached to a framebuffer.
6893 if (texture && !texture->IsAttachedToFramebuffer()) {
6894 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6895 if (image) {
6896 ScopedGLErrorSuppressor suppressor(
6897 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6898 GetErrorState());
6899 glBindTexture(textarget, texture->service_id());
6900 image->WillUseTexImage();
6901 RestoreCurrentTextureBindings(&state_, textarget);
6906 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6907 Texture* texture, GLenum textarget) {
6908 // Image is still in use if texture is attached to a framebuffer.
6909 if (texture && !texture->IsAttachedToFramebuffer()) {
6910 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6911 if (image) {
6912 ScopedGLErrorSuppressor suppressor(
6913 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6914 GetErrorState());
6915 glBindTexture(textarget, texture->service_id());
6916 image->DidUseTexImage();
6917 RestoreCurrentTextureBindings(&state_, textarget);
6922 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6923 DCHECK(state_.current_program.get());
6924 if (!texture_manager()->HaveUnrenderableTextures() &&
6925 !texture_manager()->HaveImages()) {
6926 return true;
6929 bool textures_set = false;
6930 const Program::SamplerIndices& sampler_indices =
6931 state_.current_program->sampler_indices();
6932 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6933 const Program::UniformInfo* uniform_info =
6934 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6935 DCHECK(uniform_info);
6936 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6937 GLuint texture_unit_index = uniform_info->texture_units[jj];
6938 if (texture_unit_index < state_.texture_units.size()) {
6939 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6940 TextureRef* texture_ref =
6941 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6942 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6943 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6944 textures_set = true;
6945 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6946 glBindTexture(
6947 textarget,
6948 texture_manager()->black_texture_id(uniform_info->type));
6949 if (!texture_ref) {
6950 LOCAL_RENDER_WARNING(
6951 std::string("there is no texture bound to the unit ") +
6952 base::IntToString(texture_unit_index));
6953 } else {
6954 LOCAL_RENDER_WARNING(
6955 std::string("texture bound to texture unit ") +
6956 base::IntToString(texture_unit_index) +
6957 " is not renderable. It maybe non-power-of-2 and have"
6958 " incompatible texture filtering.");
6960 continue;
6963 if (textarget != GL_TEXTURE_CUBE_MAP) {
6964 Texture* texture = texture_ref->texture();
6965 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6966 if (image && !texture->IsAttachedToFramebuffer()) {
6967 ScopedGLErrorSuppressor suppressor(
6968 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6969 textures_set = true;
6970 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6971 image->WillUseTexImage();
6972 continue;
6976 // else: should this be an error?
6979 return !textures_set;
6982 void GLES2DecoderImpl::RestoreStateForTextures() {
6983 DCHECK(state_.current_program.get());
6984 const Program::SamplerIndices& sampler_indices =
6985 state_.current_program->sampler_indices();
6986 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6987 const Program::UniformInfo* uniform_info =
6988 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6989 DCHECK(uniform_info);
6990 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6991 GLuint texture_unit_index = uniform_info->texture_units[jj];
6992 if (texture_unit_index < state_.texture_units.size()) {
6993 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6994 TextureRef* texture_ref =
6995 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6996 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6997 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6998 // Get the texture_ref info that was previously bound here.
6999 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
7000 ? texture_unit.bound_texture_2d.get()
7001 : texture_unit.bound_texture_cube_map.get();
7002 glBindTexture(texture_unit.bind_target,
7003 texture_ref ? texture_ref->service_id() : 0);
7004 continue;
7007 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7008 Texture* texture = texture_ref->texture();
7009 gfx::GLImage* image =
7010 texture->GetLevelImage(texture_unit.bind_target, 0);
7011 if (image && !texture->IsAttachedToFramebuffer()) {
7012 ScopedGLErrorSuppressor suppressor(
7013 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7014 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7015 image->DidUseTexImage();
7016 continue;
7022 // Set the active texture back to whatever the user had it as.
7023 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7026 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7027 // Only check if there are some uncleared textures.
7028 if (!texture_manager()->HaveUnsafeTextures()) {
7029 return true;
7032 // 1: Check all textures we are about to render with.
7033 if (state_.current_program.get()) {
7034 const Program::SamplerIndices& sampler_indices =
7035 state_.current_program->sampler_indices();
7036 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7037 const Program::UniformInfo* uniform_info =
7038 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7039 DCHECK(uniform_info);
7040 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7041 GLuint texture_unit_index = uniform_info->texture_units[jj];
7042 if (texture_unit_index < state_.texture_units.size()) {
7043 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7044 TextureRef* texture_ref =
7045 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7046 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7047 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7048 return false;
7055 return true;
7058 bool GLES2DecoderImpl::IsDrawValid(
7059 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7060 GLsizei primcount) {
7061 DCHECK(instanced || primcount == 1);
7063 // NOTE: We specifically do not check current_program->IsValid() because
7064 // it could never be invalid since glUseProgram would have failed. While
7065 // glLinkProgram could later mark the program as invalid the previous
7066 // valid program will still function if it is still the current program.
7067 if (!state_.current_program.get()) {
7068 // The program does not exist.
7069 // But GL says no ERROR.
7070 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7071 return false;
7074 if (CheckDrawingFeedbackLoops()) {
7075 LOCAL_SET_GL_ERROR(
7076 GL_INVALID_OPERATION, function_name,
7077 "Source and destination textures of the draw are the same.");
7078 return false;
7081 return state_.vertex_attrib_manager
7082 ->ValidateBindings(function_name,
7083 this,
7084 feature_info_.get(),
7085 state_.current_program.get(),
7086 max_vertex_accessed,
7087 instanced,
7088 primcount);
7091 bool GLES2DecoderImpl::SimulateAttrib0(
7092 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7093 DCHECK(simulated);
7094 *simulated = false;
7096 if (feature_info_->gl_version_info().BehavesLikeGLES())
7097 return true;
7099 const VertexAttrib* attrib =
7100 state_.vertex_attrib_manager->GetVertexAttrib(0);
7101 // If it's enabled or it's not used then we don't need to do anything.
7102 bool attrib_0_used =
7103 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7104 if (attrib->enabled() && attrib_0_used) {
7105 return true;
7108 // Make a buffer with a single repeated vec4 value enough to
7109 // simulate the constant value that is supposed to be here.
7110 // This is required to emulate GLES2 on GL.
7111 GLuint num_vertices = max_vertex_accessed + 1;
7112 uint32 size_needed = 0;
7114 if (num_vertices == 0 ||
7115 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7116 size_needed > 0x7FFFFFFFU) {
7117 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7118 return false;
7121 LOCAL_PERFORMANCE_WARNING(
7122 "Attribute 0 is disabled. This has signficant performance penalty");
7124 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7125 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7127 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7128 if (new_buffer) {
7129 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7130 GLenum error = glGetError();
7131 if (error != GL_NO_ERROR) {
7132 LOCAL_SET_GL_ERROR(
7133 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7134 return false;
7138 const Vec4& value = state_.attrib_values[0];
7139 if (new_buffer ||
7140 (attrib_0_used &&
7141 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7142 // TODO(zmo): This is not 100% correct because we might lose data when
7143 // casting to float type, but it is a corner case and once we migrate to
7144 // core profiles on desktop GL, it is no longer relevant.
7145 Vec4f fvalue(value);
7146 std::vector<Vec4f> temp(num_vertices, fvalue);
7147 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7148 attrib_0_buffer_matches_value_ = true;
7149 attrib_0_value_ = value;
7150 attrib_0_size_ = size_needed;
7153 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7155 if (attrib->divisor())
7156 glVertexAttribDivisorANGLE(0, 0);
7158 *simulated = true;
7159 return true;
7162 void GLES2DecoderImpl::RestoreStateForAttrib(
7163 GLuint attrib_index, bool restore_array_binding) {
7164 const VertexAttrib* attrib =
7165 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7166 if (restore_array_binding) {
7167 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7168 Buffer* buffer = attrib->buffer();
7169 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7170 glVertexAttribPointer(
7171 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7172 attrib->gl_stride(), ptr);
7174 if (attrib->divisor())
7175 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7176 glBindBuffer(
7177 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7178 state_.bound_array_buffer->service_id() : 0);
7180 // Never touch vertex attribute 0's state (in particular, never
7181 // disable it) when running on desktop GL because it will never be
7182 // re-enabled.
7183 if (attrib_index != 0 ||
7184 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7185 if (attrib->enabled()) {
7186 glEnableVertexAttribArray(attrib_index);
7187 } else {
7188 glDisableVertexAttribArray(attrib_index);
7193 bool GLES2DecoderImpl::SimulateFixedAttribs(
7194 const char* function_name,
7195 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7196 DCHECK(simulated);
7197 *simulated = false;
7198 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7199 return true;
7201 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7202 return true;
7205 LOCAL_PERFORMANCE_WARNING(
7206 "GL_FIXED attributes have a signficant performance penalty");
7208 // NOTE: we could be smart and try to check if a buffer is used
7209 // twice in 2 different attribs, find the overlapping parts and therefore
7210 // duplicate the minimum amount of data but this whole code path is not meant
7211 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7212 // tests so we just add to the buffer attrib used.
7214 GLuint elements_needed = 0;
7215 const VertexAttribManager::VertexAttribList& enabled_attribs =
7216 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7217 for (VertexAttribManager::VertexAttribList::const_iterator it =
7218 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7219 const VertexAttrib* attrib = *it;
7220 const Program::VertexAttrib* attrib_info =
7221 state_.current_program->GetAttribInfoByLocation(attrib->index());
7222 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7223 max_vertex_accessed);
7224 GLuint num_vertices = max_accessed + 1;
7225 if (num_vertices == 0) {
7226 LOCAL_SET_GL_ERROR(
7227 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7228 return false;
7230 if (attrib_info &&
7231 attrib->CanAccess(max_accessed) &&
7232 attrib->type() == GL_FIXED) {
7233 uint32 elements_used = 0;
7234 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7235 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7236 LOCAL_SET_GL_ERROR(
7237 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7238 return false;
7243 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7244 uint32 size_needed = 0;
7245 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7246 size_needed > 0x7FFFFFFFU) {
7247 LOCAL_SET_GL_ERROR(
7248 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7249 return false;
7252 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7254 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7255 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7256 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7257 GLenum error = glGetError();
7258 if (error != GL_NO_ERROR) {
7259 LOCAL_SET_GL_ERROR(
7260 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7261 return false;
7265 // Copy the elements and convert to float
7266 GLintptr offset = 0;
7267 for (VertexAttribManager::VertexAttribList::const_iterator it =
7268 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7269 const VertexAttrib* attrib = *it;
7270 const Program::VertexAttrib* attrib_info =
7271 state_.current_program->GetAttribInfoByLocation(attrib->index());
7272 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7273 max_vertex_accessed);
7274 GLuint num_vertices = max_accessed + 1;
7275 if (num_vertices == 0) {
7276 LOCAL_SET_GL_ERROR(
7277 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7278 return false;
7280 if (attrib_info &&
7281 attrib->CanAccess(max_accessed) &&
7282 attrib->type() == GL_FIXED) {
7283 int num_elements = attrib->size() * num_vertices;
7284 const int src_size = num_elements * sizeof(int32);
7285 const int dst_size = num_elements * sizeof(float);
7286 scoped_ptr<float[]> data(new float[num_elements]);
7287 const int32* src = reinterpret_cast<const int32 *>(
7288 attrib->buffer()->GetRange(attrib->offset(), src_size));
7289 const int32* end = src + num_elements;
7290 float* dst = data.get();
7291 while (src != end) {
7292 *dst++ = static_cast<float>(*src++) / 65536.0f;
7294 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7295 glVertexAttribPointer(
7296 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7297 reinterpret_cast<GLvoid*>(offset));
7298 offset += dst_size;
7301 *simulated = true;
7302 return true;
7305 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7306 // There's no need to call glVertexAttribPointer because we shadow all the
7307 // settings and passing GL_FIXED to it will not work.
7308 glBindBuffer(
7309 GL_ARRAY_BUFFER,
7310 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7311 : 0);
7314 error::Error GLES2DecoderImpl::DoDrawArrays(
7315 const char* function_name,
7316 bool instanced,
7317 GLenum mode,
7318 GLint first,
7319 GLsizei count,
7320 GLsizei primcount) {
7321 error::Error error = WillAccessBoundFramebufferForDraw();
7322 if (error != error::kNoError)
7323 return error;
7324 if (!validators_->draw_mode.IsValid(mode)) {
7325 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7326 return error::kNoError;
7328 if (count < 0) {
7329 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7330 return error::kNoError;
7332 if (primcount < 0) {
7333 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7334 return error::kNoError;
7336 if (!CheckBoundFramebuffersValid(function_name)) {
7337 return error::kNoError;
7339 // We have to check this here because the prototype for glDrawArrays
7340 // is GLint not GLsizei.
7341 if (first < 0) {
7342 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7343 return error::kNoError;
7346 if (count == 0 || primcount == 0) {
7347 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7348 return error::kNoError;
7351 GLuint max_vertex_accessed = first + count - 1;
7352 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7353 if (!ClearUnclearedTextures()) {
7354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7355 return error::kNoError;
7357 bool simulated_attrib_0 = false;
7358 if (!SimulateAttrib0(
7359 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7360 return error::kNoError;
7362 bool simulated_fixed_attribs = false;
7363 if (SimulateFixedAttribs(
7364 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7365 primcount)) {
7366 bool textures_set = !PrepareTexturesForRender();
7367 ApplyDirtyState();
7368 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7369 if (!instanced) {
7370 glDrawArrays(mode, first, count);
7371 } else {
7372 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7374 if (textures_set) {
7375 RestoreStateForTextures();
7377 if (simulated_fixed_attribs) {
7378 RestoreStateForSimulatedFixedAttribs();
7381 if (simulated_attrib_0) {
7382 // We don't have to restore attrib 0 generic data at the end of this
7383 // function even if it is simulated. This is because we will simulate
7384 // it in each draw call, and attrib 0 generic data queries use cached
7385 // values instead of passing down to the underlying driver.
7386 RestoreStateForAttrib(0, false);
7389 return error::kNoError;
7392 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7393 const void* cmd_data) {
7394 // TODO(zmo): crbug.com/481184
7395 // On Desktop GL with versions lower than 4.3, we need to emulate
7396 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7397 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7398 return DoDrawArrays("glDrawArrays",
7399 false,
7400 static_cast<GLenum>(c.mode),
7401 static_cast<GLint>(c.first),
7402 static_cast<GLsizei>(c.count),
7406 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7407 uint32 immediate_data_size,
7408 const void* cmd_data) {
7409 const gles2::cmds::DrawArraysInstancedANGLE& c =
7410 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7411 if (!features().angle_instanced_arrays) {
7412 LOCAL_SET_GL_ERROR(
7413 GL_INVALID_OPERATION,
7414 "glDrawArraysInstancedANGLE", "function not available");
7415 return error::kNoError;
7417 return DoDrawArrays("glDrawArraysIntancedANGLE",
7418 true,
7419 static_cast<GLenum>(c.mode),
7420 static_cast<GLint>(c.first),
7421 static_cast<GLsizei>(c.count),
7422 static_cast<GLsizei>(c.primcount));
7425 error::Error GLES2DecoderImpl::DoDrawElements(
7426 const char* function_name,
7427 bool instanced,
7428 GLenum mode,
7429 GLsizei count,
7430 GLenum type,
7431 int32 offset,
7432 GLsizei primcount) {
7433 error::Error error = WillAccessBoundFramebufferForDraw();
7434 if (error != error::kNoError)
7435 return error;
7436 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7437 LOCAL_SET_GL_ERROR(
7438 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7439 return error::kNoError;
7442 if (count < 0) {
7443 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7444 return error::kNoError;
7446 if (offset < 0) {
7447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7448 return error::kNoError;
7450 if (!validators_->draw_mode.IsValid(mode)) {
7451 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7452 return error::kNoError;
7454 if (!validators_->index_type.IsValid(type)) {
7455 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7456 return error::kNoError;
7458 if (primcount < 0) {
7459 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7460 return error::kNoError;
7463 if (!CheckBoundFramebuffersValid(function_name)) {
7464 return error::kNoError;
7467 if (count == 0 || primcount == 0) {
7468 return error::kNoError;
7471 GLuint max_vertex_accessed;
7472 Buffer* element_array_buffer =
7473 state_.vertex_attrib_manager->element_array_buffer();
7475 if (!element_array_buffer->GetMaxValueForRange(
7476 offset, count, type, &max_vertex_accessed)) {
7477 LOCAL_SET_GL_ERROR(
7478 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7479 return error::kNoError;
7482 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7483 if (!ClearUnclearedTextures()) {
7484 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7485 return error::kNoError;
7487 bool simulated_attrib_0 = false;
7488 if (!SimulateAttrib0(
7489 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7490 return error::kNoError;
7492 bool simulated_fixed_attribs = false;
7493 if (SimulateFixedAttribs(
7494 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7495 primcount)) {
7496 bool textures_set = !PrepareTexturesForRender();
7497 ApplyDirtyState();
7498 // TODO(gman): Refactor to hide these details in BufferManager or
7499 // VertexAttribManager.
7500 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7501 bool used_client_side_array = false;
7502 if (element_array_buffer->IsClientSideArray()) {
7503 used_client_side_array = true;
7504 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7505 indices = element_array_buffer->GetRange(offset, 0);
7508 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7509 if (!instanced) {
7510 glDrawElements(mode, count, type, indices);
7511 } else {
7512 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7515 if (used_client_side_array) {
7516 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7517 element_array_buffer->service_id());
7520 if (textures_set) {
7521 RestoreStateForTextures();
7523 if (simulated_fixed_attribs) {
7524 RestoreStateForSimulatedFixedAttribs();
7527 if (simulated_attrib_0) {
7528 // We don't have to restore attrib 0 generic data at the end of this
7529 // function even if it is simulated. This is because we will simulate
7530 // it in each draw call, and attrib 0 generic data queries use cached
7531 // values instead of passing down to the underlying driver.
7532 RestoreStateForAttrib(0, false);
7535 return error::kNoError;
7538 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7539 const void* cmd_data) {
7540 // TODO(zmo): crbug.com/481184
7541 // On Desktop GL with versions lower than 4.3, we need to emulate
7542 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7543 const gles2::cmds::DrawElements& c =
7544 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7545 return DoDrawElements("glDrawElements",
7546 false,
7547 static_cast<GLenum>(c.mode),
7548 static_cast<GLsizei>(c.count),
7549 static_cast<GLenum>(c.type),
7550 static_cast<int32>(c.index_offset),
7554 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7555 uint32 immediate_data_size,
7556 const void* cmd_data) {
7557 const gles2::cmds::DrawElementsInstancedANGLE& c =
7558 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7559 if (!features().angle_instanced_arrays) {
7560 LOCAL_SET_GL_ERROR(
7561 GL_INVALID_OPERATION,
7562 "glDrawElementsInstancedANGLE", "function not available");
7563 return error::kNoError;
7565 return DoDrawElements("glDrawElementsInstancedANGLE",
7566 true,
7567 static_cast<GLenum>(c.mode),
7568 static_cast<GLsizei>(c.count),
7569 static_cast<GLenum>(c.type),
7570 static_cast<int32>(c.index_offset),
7571 static_cast<GLsizei>(c.primcount));
7574 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7575 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7576 GLuint max_vertex_accessed = 0;
7577 Buffer* buffer = GetBuffer(buffer_id);
7578 if (!buffer) {
7579 // TODO(gman): Should this be a GL error or a command buffer error?
7580 LOCAL_SET_GL_ERROR(
7581 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7582 } else {
7583 if (!buffer->GetMaxValueForRange(
7584 offset, count, type, &max_vertex_accessed)) {
7585 // TODO(gman): Should this be a GL error or a command buffer error?
7586 LOCAL_SET_GL_ERROR(
7587 GL_INVALID_OPERATION,
7588 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7591 return max_vertex_accessed;
7594 void GLES2DecoderImpl::DoShaderSource(
7595 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7596 std::string str;
7597 for (GLsizei ii = 0; ii < count; ++ii) {
7598 if (length && length[ii] > 0)
7599 str.append(data[ii], length[ii]);
7600 else
7601 str.append(data[ii]);
7603 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7604 if (!shader) {
7605 return;
7607 // Note: We don't actually call glShaderSource here. We wait until
7608 // we actually compile the shader.
7609 shader->set_source(str);
7612 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7613 GLuint client_program_id, GLsizei count, const char* const* varyings,
7614 GLenum buffer_mode) {
7615 Program* program = GetProgramInfoNotShader(
7616 client_program_id, "glTransformFeedbackVaryings");
7617 if (!program) {
7618 return;
7620 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7621 glTransformFeedbackVaryings(
7622 program->service_id(), count, varyings, buffer_mode);
7625 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7626 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7627 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7628 if (!shader) {
7629 return;
7632 scoped_refptr<ShaderTranslatorInterface> translator;
7633 if (use_shader_translator_) {
7634 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7635 vertex_translator_ : fragment_translator_;
7638 const Shader::TranslatedShaderSourceType source_type =
7639 feature_info_->feature_flags().angle_translated_shader_source ?
7640 Shader::kANGLE : Shader::kGL;
7641 shader->RequestCompile(translator, source_type);
7644 void GLES2DecoderImpl::DoGetShaderiv(
7645 GLuint shader_id, GLenum pname, GLint* params) {
7646 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7647 if (!shader) {
7648 return;
7651 // Compile now for statuses that require it.
7652 switch (pname) {
7653 case GL_COMPILE_STATUS:
7654 case GL_INFO_LOG_LENGTH:
7655 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7656 shader->DoCompile();
7657 break;
7659 default:
7660 break;
7663 switch (pname) {
7664 case GL_SHADER_SOURCE_LENGTH:
7665 *params = shader->source().size();
7666 if (*params)
7667 ++(*params);
7668 return;
7669 case GL_COMPILE_STATUS:
7670 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7671 return;
7672 case GL_INFO_LOG_LENGTH:
7673 *params = shader->log_info().size();
7674 if (*params)
7675 ++(*params);
7676 return;
7677 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7678 *params = shader->translated_source().size();
7679 if (*params)
7680 ++(*params);
7681 return;
7682 default:
7683 break;
7685 glGetShaderiv(shader->service_id(), pname, params);
7688 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7689 const void* cmd_data) {
7690 const gles2::cmds::GetShaderSource& c =
7691 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7692 GLuint shader_id = c.shader;
7693 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7694 Bucket* bucket = CreateBucket(bucket_id);
7695 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7696 if (!shader || shader->source().empty()) {
7697 bucket->SetSize(0);
7698 return error::kNoError;
7700 bucket->SetFromString(shader->source().c_str());
7701 return error::kNoError;
7704 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7705 uint32 immediate_data_size,
7706 const void* cmd_data) {
7707 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7708 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7709 cmd_data);
7710 GLuint shader_id = c.shader;
7711 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7712 Bucket* bucket = CreateBucket(bucket_id);
7713 Shader* shader = GetShaderInfoNotProgram(
7714 shader_id, "glGetTranslatedShaderSourceANGLE");
7715 if (!shader) {
7716 bucket->SetSize(0);
7717 return error::kNoError;
7720 // Make sure translator has been utilized in compile.
7721 shader->DoCompile();
7723 bucket->SetFromString(shader->translated_source().c_str());
7724 return error::kNoError;
7727 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7728 uint32 immediate_data_size,
7729 const void* cmd_data) {
7730 const gles2::cmds::GetProgramInfoLog& c =
7731 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7732 GLuint program_id = c.program;
7733 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7734 Bucket* bucket = CreateBucket(bucket_id);
7735 Program* program = GetProgramInfoNotShader(
7736 program_id, "glGetProgramInfoLog");
7737 if (!program || !program->log_info()) {
7738 bucket->SetFromString("");
7739 return error::kNoError;
7741 bucket->SetFromString(program->log_info()->c_str());
7742 return error::kNoError;
7745 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7746 uint32 immediate_data_size,
7747 const void* cmd_data) {
7748 const gles2::cmds::GetShaderInfoLog& c =
7749 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7750 GLuint shader_id = c.shader;
7751 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7752 Bucket* bucket = CreateBucket(bucket_id);
7753 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7754 if (!shader) {
7755 bucket->SetFromString("");
7756 return error::kNoError;
7759 // Shader must be compiled in order to get the info log.
7760 shader->DoCompile();
7762 bucket->SetFromString(shader->log_info().c_str());
7763 return error::kNoError;
7766 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7767 return state_.GetEnabled(cap);
7770 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7771 const Buffer* buffer = GetBuffer(client_id);
7772 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7775 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7776 const Framebuffer* framebuffer =
7777 GetFramebuffer(client_id);
7778 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7781 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7782 // IsProgram is true for programs as soon as they are created, until they are
7783 // deleted and no longer in use.
7784 const Program* program = GetProgram(client_id);
7785 return program != NULL && !program->IsDeleted();
7788 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7789 const Renderbuffer* renderbuffer =
7790 GetRenderbuffer(client_id);
7791 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7794 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7795 // IsShader is true for shaders as soon as they are created, until they
7796 // are deleted and not attached to any programs.
7797 const Shader* shader = GetShader(client_id);
7798 return shader != NULL && !shader->IsDeleted();
7801 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7802 const TextureRef* texture_ref = GetTexture(client_id);
7803 return texture_ref && texture_ref->texture()->IsValid();
7806 void GLES2DecoderImpl::DoAttachShader(
7807 GLuint program_client_id, GLint shader_client_id) {
7808 Program* program = GetProgramInfoNotShader(
7809 program_client_id, "glAttachShader");
7810 if (!program) {
7811 return;
7813 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7814 if (!shader) {
7815 return;
7817 if (!program->AttachShader(shader_manager(), shader)) {
7818 LOCAL_SET_GL_ERROR(
7819 GL_INVALID_OPERATION,
7820 "glAttachShader",
7821 "can not attach more than one shader of the same type.");
7822 return;
7824 glAttachShader(program->service_id(), shader->service_id());
7827 void GLES2DecoderImpl::DoDetachShader(
7828 GLuint program_client_id, GLint shader_client_id) {
7829 Program* program = GetProgramInfoNotShader(
7830 program_client_id, "glDetachShader");
7831 if (!program) {
7832 return;
7834 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7835 if (!shader) {
7836 return;
7838 if (!program->DetachShader(shader_manager(), shader)) {
7839 LOCAL_SET_GL_ERROR(
7840 GL_INVALID_OPERATION,
7841 "glDetachShader", "shader not attached to program");
7842 return;
7844 glDetachShader(program->service_id(), shader->service_id());
7847 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7848 Program* program = GetProgramInfoNotShader(
7849 program_client_id, "glValidateProgram");
7850 if (!program) {
7851 return;
7853 program->Validate();
7856 void GLES2DecoderImpl::GetVertexAttribHelper(
7857 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7858 switch (pname) {
7859 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7861 Buffer* buffer = attrib->buffer();
7862 if (buffer && !buffer->IsDeleted()) {
7863 GLuint client_id;
7864 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7865 *params = client_id;
7867 break;
7869 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7870 *params = attrib->enabled();
7871 break;
7872 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7873 *params = attrib->size();
7874 break;
7875 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7876 *params = attrib->gl_stride();
7877 break;
7878 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7879 *params = attrib->type();
7880 break;
7881 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7882 *params = attrib->normalized();
7883 break;
7884 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7885 *params = attrib->divisor();
7886 break;
7887 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7888 *params = attrib->integer();
7889 break;
7890 default:
7891 NOTREACHED();
7892 break;
7896 void GLES2DecoderImpl::DoGetTexParameterfv(
7897 GLenum target, GLenum pname, GLfloat* params) {
7898 InitTextureMaxAnisotropyIfNeeded(target, pname);
7899 glGetTexParameterfv(target, pname, params);
7902 void GLES2DecoderImpl::DoGetTexParameteriv(
7903 GLenum target, GLenum pname, GLint* params) {
7904 InitTextureMaxAnisotropyIfNeeded(target, pname);
7905 glGetTexParameteriv(target, pname, params);
7908 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7909 GLenum target, GLenum pname) {
7910 if (!workarounds().init_texture_max_anisotropy)
7911 return;
7912 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7913 !validators_->texture_parameter.IsValid(pname)) {
7914 return;
7917 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7918 &state_, target);
7919 if (!texture_ref) {
7920 LOCAL_SET_GL_ERROR(
7921 GL_INVALID_OPERATION,
7922 "glGetTexParamter{fi}v", "unknown texture for target");
7923 return;
7925 Texture* texture = texture_ref->texture();
7926 texture->InitTextureMaxAnisotropyIfNeeded(target);
7929 template <typename T>
7930 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7931 GLuint index, GLenum pname, T* params) {
7932 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7933 if (!attrib) {
7934 LOCAL_SET_GL_ERROR(
7935 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7936 return;
7938 switch (pname) {
7939 case GL_CURRENT_VERTEX_ATTRIB:
7940 state_.attrib_values[index].GetValues(params);
7941 break;
7942 default: {
7943 GLint value = 0;
7944 GetVertexAttribHelper(attrib, pname, &value);
7945 *params = static_cast<T>(value);
7946 break;
7951 void GLES2DecoderImpl::DoGetVertexAttribfv(
7952 GLuint index, GLenum pname, GLfloat* params) {
7953 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7956 void GLES2DecoderImpl::DoGetVertexAttribiv(
7957 GLuint index, GLenum pname, GLint* params) {
7958 DoGetVertexAttribImpl<GLint>(index, pname, params);
7961 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7962 GLuint index, GLenum pname, GLint* params) {
7963 DoGetVertexAttribImpl<GLint>(index, pname, params);
7966 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7967 GLuint index, GLenum pname, GLuint* params) {
7968 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7971 template <typename T>
7972 bool GLES2DecoderImpl::SetVertexAttribValue(
7973 const char* function_name, GLuint index, const T* value) {
7974 if (index >= state_.attrib_values.size()) {
7975 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7976 return false;
7978 state_.attrib_values[index].SetValues(value);
7979 return true;
7982 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7983 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7984 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7985 glVertexAttrib1f(index, v0);
7989 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7990 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7991 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7992 glVertexAttrib2f(index, v0, v1);
7996 void GLES2DecoderImpl::DoVertexAttrib3f(
7997 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7998 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7999 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
8000 glVertexAttrib3f(index, v0, v1, v2);
8004 void GLES2DecoderImpl::DoVertexAttrib4f(
8005 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
8006 GLfloat v[4] = { v0, v1, v2, v3, };
8007 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8008 glVertexAttrib4f(index, v0, v1, v2, v3);
8012 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8013 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8014 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8015 glVertexAttrib1fv(index, v);
8019 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8020 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8021 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8022 glVertexAttrib2fv(index, v);
8026 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8027 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8028 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8029 glVertexAttrib3fv(index, v);
8033 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8034 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8035 glVertexAttrib4fv(index, v);
8039 void GLES2DecoderImpl::DoVertexAttribI4i(
8040 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8041 GLint v[4] = { v0, v1, v2, v3 };
8042 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8043 glVertexAttribI4i(index, v0, v1, v2, v3);
8047 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8048 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8049 glVertexAttribI4iv(index, v);
8053 void GLES2DecoderImpl::DoVertexAttribI4ui(
8054 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8055 GLuint v[4] = { v0, v1, v2, v3 };
8056 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8057 glVertexAttribI4ui(index, v0, v1, v2, v3);
8061 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8062 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8063 glVertexAttribI4uiv(index, v);
8067 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8068 uint32 immediate_data_size,
8069 const void* cmd_data) {
8070 if (!unsafe_es3_apis_enabled())
8071 return error::kUnknownCommand;
8072 const gles2::cmds::VertexAttribIPointer& c =
8073 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8075 if (!state_.bound_array_buffer.get() ||
8076 state_.bound_array_buffer->IsDeleted()) {
8077 if (state_.vertex_attrib_manager.get() ==
8078 state_.default_vertex_attrib_manager.get()) {
8079 LOCAL_SET_GL_ERROR(
8080 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8081 return error::kNoError;
8082 } else if (c.offset != 0) {
8083 LOCAL_SET_GL_ERROR(
8084 GL_INVALID_VALUE,
8085 "glVertexAttribIPointer", "client side arrays are not allowed");
8086 return error::kNoError;
8090 GLuint indx = c.indx;
8091 GLint size = c.size;
8092 GLenum type = c.type;
8093 GLsizei stride = c.stride;
8094 GLsizei offset = c.offset;
8095 const void* ptr = reinterpret_cast<const void*>(offset);
8096 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8097 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8098 return error::kNoError;
8100 if (!validators_->vertex_attrib_size.IsValid(size)) {
8101 LOCAL_SET_GL_ERROR(
8102 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8103 return error::kNoError;
8105 if (indx >= group_->max_vertex_attribs()) {
8106 LOCAL_SET_GL_ERROR(
8107 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8108 return error::kNoError;
8110 if (stride < 0) {
8111 LOCAL_SET_GL_ERROR(
8112 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8113 return error::kNoError;
8115 if (stride > 255) {
8116 LOCAL_SET_GL_ERROR(
8117 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8118 return error::kNoError;
8120 if (offset < 0) {
8121 LOCAL_SET_GL_ERROR(
8122 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8123 return error::kNoError;
8125 GLsizei component_size =
8126 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8127 // component_size must be a power of two to use & as optimized modulo.
8128 DCHECK(GLES2Util::IsPOT(component_size));
8129 if (offset & (component_size - 1)) {
8130 LOCAL_SET_GL_ERROR(
8131 GL_INVALID_OPERATION,
8132 "glVertexAttribIPointer", "offset not valid for type");
8133 return error::kNoError;
8135 if (stride & (component_size - 1)) {
8136 LOCAL_SET_GL_ERROR(
8137 GL_INVALID_OPERATION,
8138 "glVertexAttribIPointer", "stride not valid for type");
8139 return error::kNoError;
8141 state_.vertex_attrib_manager
8142 ->SetAttribInfo(indx,
8143 state_.bound_array_buffer.get(),
8144 size,
8145 type,
8146 GL_FALSE,
8147 stride,
8148 stride != 0 ? stride : component_size * size,
8149 offset,
8150 GL_TRUE);
8151 glVertexAttribIPointer(indx, size, type, stride, ptr);
8152 return error::kNoError;
8155 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8156 uint32 immediate_data_size,
8157 const void* cmd_data) {
8158 const gles2::cmds::VertexAttribPointer& c =
8159 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8161 if (!state_.bound_array_buffer.get() ||
8162 state_.bound_array_buffer->IsDeleted()) {
8163 if (state_.vertex_attrib_manager.get() ==
8164 state_.default_vertex_attrib_manager.get()) {
8165 LOCAL_SET_GL_ERROR(
8166 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8167 return error::kNoError;
8168 } else if (c.offset != 0) {
8169 LOCAL_SET_GL_ERROR(
8170 GL_INVALID_VALUE,
8171 "glVertexAttribPointer", "client side arrays are not allowed");
8172 return error::kNoError;
8176 GLuint indx = c.indx;
8177 GLint size = c.size;
8178 GLenum type = c.type;
8179 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8180 GLsizei stride = c.stride;
8181 GLsizei offset = c.offset;
8182 const void* ptr = reinterpret_cast<const void*>(offset);
8183 if (!validators_->vertex_attrib_type.IsValid(type)) {
8184 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8185 return error::kNoError;
8187 if (!validators_->vertex_attrib_size.IsValid(size)) {
8188 LOCAL_SET_GL_ERROR(
8189 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8190 return error::kNoError;
8192 if (indx >= group_->max_vertex_attribs()) {
8193 LOCAL_SET_GL_ERROR(
8194 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8195 return error::kNoError;
8197 if (stride < 0) {
8198 LOCAL_SET_GL_ERROR(
8199 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8200 return error::kNoError;
8202 if (stride > 255) {
8203 LOCAL_SET_GL_ERROR(
8204 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8205 return error::kNoError;
8207 if (offset < 0) {
8208 LOCAL_SET_GL_ERROR(
8209 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8210 return error::kNoError;
8212 GLsizei component_size =
8213 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8214 // component_size must be a power of two to use & as optimized modulo.
8215 DCHECK(GLES2Util::IsPOT(component_size));
8216 if (offset & (component_size - 1)) {
8217 LOCAL_SET_GL_ERROR(
8218 GL_INVALID_OPERATION,
8219 "glVertexAttribPointer", "offset not valid for type");
8220 return error::kNoError;
8222 if (stride & (component_size - 1)) {
8223 LOCAL_SET_GL_ERROR(
8224 GL_INVALID_OPERATION,
8225 "glVertexAttribPointer", "stride not valid for type");
8226 return error::kNoError;
8228 state_.vertex_attrib_manager
8229 ->SetAttribInfo(indx,
8230 state_.bound_array_buffer.get(),
8231 size,
8232 type,
8233 normalized,
8234 stride,
8235 stride != 0 ? stride : component_size * size,
8236 offset,
8237 GL_FALSE);
8238 // We support GL_FIXED natively on EGL/GLES2 implementations
8239 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8240 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8242 return error::kNoError;
8245 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8246 GLsizei height) {
8247 state_.viewport_x = x;
8248 state_.viewport_y = y;
8249 state_.viewport_width = std::min(width, viewport_max_width_);
8250 state_.viewport_height = std::min(height, viewport_max_height_);
8251 glViewport(x, y, width, height);
8254 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8255 uint32 immediate_data_size,
8256 const void* cmd_data) {
8257 const gles2::cmds::VertexAttribDivisorANGLE& c =
8258 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8259 if (!features().angle_instanced_arrays) {
8260 LOCAL_SET_GL_ERROR(
8261 GL_INVALID_OPERATION,
8262 "glVertexAttribDivisorANGLE", "function not available");
8263 return error::kNoError;
8265 GLuint index = c.index;
8266 GLuint divisor = c.divisor;
8267 if (index >= group_->max_vertex_attribs()) {
8268 LOCAL_SET_GL_ERROR(
8269 GL_INVALID_VALUE,
8270 "glVertexAttribDivisorANGLE", "index out of range");
8271 return error::kNoError;
8274 state_.vertex_attrib_manager->SetDivisor(
8275 index,
8276 divisor);
8277 glVertexAttribDivisorANGLE(index, divisor);
8278 return error::kNoError;
8281 template <typename pixel_data_type>
8282 static void WriteAlphaData(
8283 void* pixels, uint32 row_count, uint32 channel_count,
8284 uint32 alpha_channel_index, uint32 unpadded_row_size,
8285 uint32 padded_row_size, pixel_data_type alpha_value) {
8286 DCHECK_GT(channel_count, 0U);
8287 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8288 uint32 unpadded_row_size_in_elements =
8289 unpadded_row_size / sizeof(pixel_data_type);
8290 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8291 uint32 padded_row_size_in_elements =
8292 padded_row_size / sizeof(pixel_data_type);
8293 pixel_data_type* dst =
8294 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8295 for (uint32 yy = 0; yy < row_count; ++yy) {
8296 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8297 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8298 *d = alpha_value;
8300 dst += padded_row_size_in_elements;
8304 void GLES2DecoderImpl::FinishReadPixels(
8305 const cmds::ReadPixels& c,
8306 GLuint buffer) {
8307 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8308 GLsizei width = c.width;
8309 GLsizei height = c.height;
8310 GLenum format = c.format;
8311 GLenum type = c.type;
8312 typedef cmds::ReadPixels::Result Result;
8313 uint32 pixels_size;
8314 Result* result = NULL;
8315 if (c.result_shm_id != 0) {
8316 result = GetSharedMemoryAs<Result*>(
8317 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8318 if (!result) {
8319 if (buffer != 0) {
8320 glDeleteBuffersARB(1, &buffer);
8322 return;
8325 GLES2Util::ComputeImageDataSizes(
8326 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8327 NULL, NULL);
8328 void* pixels = GetSharedMemoryAs<void*>(
8329 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8330 if (!pixels) {
8331 if (buffer != 0) {
8332 glDeleteBuffersARB(1, &buffer);
8334 return;
8337 if (buffer != 0) {
8338 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8339 void* data;
8340 if (features().map_buffer_range) {
8341 data = glMapBufferRange(
8342 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8343 } else {
8344 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8346 if (!data) {
8347 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8348 "Unable to map memory for readback.");
8349 return;
8351 memcpy(pixels, data, pixels_size);
8352 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8353 // have to restore the state.
8354 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8355 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8356 glDeleteBuffersARB(1, &buffer);
8359 if (result != NULL) {
8360 *result = true;
8363 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8364 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8365 if ((channels_exist & 0x0008) == 0 &&
8366 workarounds().clear_alpha_in_readpixels) {
8367 // Set the alpha to 255 because some drivers are buggy in this regard.
8368 uint32 temp_size;
8370 uint32 unpadded_row_size;
8371 uint32 padded_row_size;
8372 if (!GLES2Util::ComputeImageDataSizes(
8373 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8374 &unpadded_row_size, &padded_row_size)) {
8375 return;
8378 uint32 channel_count = 0;
8379 uint32 alpha_channel = 0;
8380 switch (format) {
8381 case GL_RGBA:
8382 case GL_BGRA_EXT:
8383 channel_count = 4;
8384 alpha_channel = 3;
8385 break;
8386 case GL_ALPHA:
8387 channel_count = 1;
8388 alpha_channel = 0;
8389 break;
8392 if (channel_count > 0) {
8393 switch (type) {
8394 case GL_UNSIGNED_BYTE:
8395 WriteAlphaData<uint8>(
8396 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8397 padded_row_size, 0xFF);
8398 break;
8399 case GL_FLOAT:
8400 WriteAlphaData<float>(
8401 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8402 padded_row_size, 1.0f);
8403 break;
8404 case GL_HALF_FLOAT:
8405 WriteAlphaData<uint16>(
8406 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8407 padded_row_size, 0x3C00);
8408 break;
8414 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8415 const void* cmd_data) {
8416 const gles2::cmds::ReadPixels& c =
8417 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8418 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8419 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8420 if (fbo_error != error::kNoError)
8421 return fbo_error;
8422 GLint x = c.x;
8423 GLint y = c.y;
8424 GLsizei width = c.width;
8425 GLsizei height = c.height;
8426 GLenum format = c.format;
8427 GLenum type = c.type;
8428 GLboolean async = static_cast<GLboolean>(c.async);
8429 if (width < 0 || height < 0) {
8430 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8431 return error::kNoError;
8433 typedef cmds::ReadPixels::Result Result;
8434 uint32 pixels_size;
8435 if (!GLES2Util::ComputeImageDataSizes(
8436 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8437 NULL, NULL)) {
8438 return error::kOutOfBounds;
8440 void* pixels = GetSharedMemoryAs<void*>(
8441 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8442 if (!pixels) {
8443 return error::kOutOfBounds;
8445 Result* result = NULL;
8446 if (c.result_shm_id != 0) {
8447 result = GetSharedMemoryAs<Result*>(
8448 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8449 if (!result) {
8450 return error::kOutOfBounds;
8454 if (!validators_->read_pixel_format.IsValid(format)) {
8455 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8456 return error::kNoError;
8458 if (!validators_->read_pixel_type.IsValid(type)) {
8459 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8460 return error::kNoError;
8463 GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
8464 if (src_internal_format == 0) {
8465 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels",
8466 "no valid read buffer source");
8467 return error::kNoError;
8469 std::vector<GLenum> accepted_formats;
8470 std::vector<GLenum> accepted_types;
8471 switch (src_internal_format) {
8472 case GL_RGB10_A2UI:
8473 accepted_formats.push_back(GL_RGBA);
8474 accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV);
8475 case GL_R8UI:
8476 case GL_R16UI:
8477 case GL_R32UI:
8478 case GL_RG8UI:
8479 case GL_RG16UI:
8480 case GL_RG32UI:
8481 // All the RGB_INTEGER formats are not renderable.
8482 case GL_RGBA8UI:
8483 case GL_RGBA16UI:
8484 case GL_RGBA32UI:
8485 accepted_formats.push_back(GL_RGBA_INTEGER);
8486 accepted_types.push_back(GL_UNSIGNED_INT);
8487 break;
8488 case GL_R8I:
8489 case GL_R16I:
8490 case GL_R32I:
8491 case GL_RG8I:
8492 case GL_RG16I:
8493 case GL_RG32I:
8494 case GL_RGBA8I:
8495 case GL_RGBA16I:
8496 case GL_RGBA32I:
8497 accepted_formats.push_back(GL_RGBA_INTEGER);
8498 accepted_types.push_back(GL_INT);
8499 break;
8500 default:
8501 accepted_formats.push_back(GL_RGBA);
8503 GLenum src_type = GetBoundReadFrameBufferTextureType();
8504 switch (src_type) {
8505 case GL_HALF_FLOAT:
8506 case GL_HALF_FLOAT_OES:
8507 case GL_FLOAT:
8508 case GL_UNSIGNED_INT_10F_11F_11F_REV:
8509 accepted_types.push_back(GL_FLOAT);
8510 break;
8511 default:
8512 accepted_types.push_back(GL_UNSIGNED_BYTE);
8513 break;
8516 break;
8518 if (!IsWebGLContext()) {
8519 accepted_formats.push_back(GL_BGRA_EXT);
8520 accepted_types.push_back(GL_UNSIGNED_BYTE);
8522 DCHECK_EQ(accepted_formats.size(), accepted_types.size());
8523 bool format_type_acceptable = false;
8524 for (size_t ii = 0; ii < accepted_formats.size(); ++ii) {
8525 if (format == accepted_formats[ii] && type == accepted_types[ii]) {
8526 format_type_acceptable = true;
8527 break;
8530 if (!format_type_acceptable) {
8531 // format and type are acceptable enums but not guaranteed to be supported
8532 // for this framebuffer. Have to ask gl if they are valid.
8533 GLint preferred_format = 0;
8534 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8535 GLint preferred_type = 0;
8536 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8537 if (format == static_cast<GLenum>(preferred_format) &&
8538 type == static_cast<GLenum>(preferred_type)) {
8539 format_type_acceptable = true;
8542 if (!format_type_acceptable) {
8543 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels",
8544 "format and type incompatible with the current read framebuffer");
8545 return error::kNoError;
8547 if (width == 0 || height == 0) {
8548 return error::kNoError;
8551 // Get the size of the current fbo or backbuffer.
8552 gfx::Size max_size = GetBoundReadFrameBufferSize();
8554 int32 max_x;
8555 int32 max_y;
8556 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8557 LOCAL_SET_GL_ERROR(
8558 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8559 return error::kNoError;
8562 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8563 return error::kNoError;
8566 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8568 ScopedResolvedFrameBufferBinder binder(this, false, true);
8570 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8571 // The user requested an out of range area. Get the results 1 line
8572 // at a time.
8573 uint32 temp_size;
8574 uint32 unpadded_row_size;
8575 uint32 padded_row_size;
8576 if (!GLES2Util::ComputeImageDataSizes(
8577 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8578 &unpadded_row_size, &padded_row_size)) {
8579 LOCAL_SET_GL_ERROR(
8580 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8581 return error::kNoError;
8584 GLint dest_x_offset = std::max(-x, 0);
8585 uint32 dest_row_offset;
8586 if (!GLES2Util::ComputeImageDataSizes(
8587 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8588 &dest_row_offset, NULL, NULL)) {
8589 LOCAL_SET_GL_ERROR(
8590 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8591 return error::kNoError;
8594 // Copy each row into the larger dest rect.
8595 int8* dst = static_cast<int8*>(pixels);
8596 GLint read_x = std::max(0, x);
8597 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8598 GLint read_width = read_end_x - read_x;
8599 for (GLint yy = 0; yy < height; ++yy) {
8600 GLint ry = y + yy;
8602 // Clear the row.
8603 memset(dst, 0, unpadded_row_size);
8605 // If the row is in range, copy it.
8606 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8607 glReadPixels(
8608 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8610 dst += padded_row_size;
8612 } else {
8613 if (async && features().use_async_readpixels) {
8614 GLuint buffer = 0;
8615 glGenBuffersARB(1, &buffer);
8616 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8617 // For ANGLE client version 2, GL_STREAM_READ is not available.
8618 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8619 GL_STATIC_DRAW : GL_STREAM_READ;
8620 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8621 GLenum error = glGetError();
8622 if (error == GL_NO_ERROR) {
8623 glReadPixels(x, y, width, height, format, type, 0);
8624 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8625 new FenceCallback()));
8626 WaitForReadPixels(base::Bind(
8627 &GLES2DecoderImpl::FinishReadPixels,
8628 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8629 <GLES2DecoderImpl>(this),
8630 c, buffer));
8631 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8632 return error::kNoError;
8633 } else {
8634 // On error, unbind pack buffer and fall through to sync readpixels
8635 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8636 glDeleteBuffersARB(1, &buffer);
8639 glReadPixels(x, y, width, height, format, type, pixels);
8641 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8642 if (error == GL_NO_ERROR) {
8643 if (result != NULL) {
8644 *result = true;
8646 FinishReadPixels(c, 0);
8649 return error::kNoError;
8652 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8653 const void* cmd_data) {
8654 const gles2::cmds::PixelStorei& c =
8655 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8656 GLenum pname = c.pname;
8657 GLenum param = c.param;
8658 if (!validators_->pixel_store.IsValid(pname)) {
8659 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8660 return error::kNoError;
8662 switch (pname) {
8663 case GL_PACK_ALIGNMENT:
8664 case GL_UNPACK_ALIGNMENT:
8665 if (!validators_->pixel_store_alignment.IsValid(param)) {
8666 LOCAL_SET_GL_ERROR(
8667 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8668 return error::kNoError;
8670 break;
8671 default:
8672 break;
8674 glPixelStorei(pname, param);
8675 switch (pname) {
8676 case GL_PACK_ALIGNMENT:
8677 state_.pack_alignment = param;
8678 break;
8679 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8680 state_.pack_reverse_row_order = (param != 0);
8681 break;
8682 case GL_UNPACK_ALIGNMENT:
8683 state_.unpack_alignment = param;
8684 break;
8685 default:
8686 // Validation should have prevented us from getting here.
8687 NOTREACHED();
8688 break;
8690 return error::kNoError;
8693 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8694 uint32 immediate_data_size,
8695 const void* cmd_data) {
8696 const gles2::cmds::PostSubBufferCHROMIUM& c =
8697 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8698 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8700 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8702 if (!supports_post_sub_buffer_) {
8703 LOCAL_SET_GL_ERROR(
8704 GL_INVALID_OPERATION,
8705 "glPostSubBufferCHROMIUM", "command not supported by surface");
8706 return error::kNoError;
8708 bool is_tracing;
8709 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8710 &is_tracing);
8711 if (is_tracing) {
8712 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8713 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8714 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8715 is_offscreen ? offscreen_size_ : surface_->GetSize());
8717 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8718 gfx::SwapResult::SWAP_FAILED) {
8719 return error::kNoError;
8720 } else {
8721 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8722 return error::kLostContext;
8726 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8727 uint32 immediate_data_size,
8728 const void* cmd_data) {
8729 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8730 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8731 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8732 if (!ref) {
8733 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8734 "glScheduleOverlayPlaneCHROMIUM",
8735 "unknown texture");
8736 return error::kNoError;
8738 gfx::GLImage* image =
8739 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8740 if (!image) {
8741 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8742 "glScheduleOverlayPlaneCHROMIUM",
8743 "unsupported texture format");
8744 return error::kNoError;
8746 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8747 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8748 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8749 "glScheduleOverlayPlaneCHROMIUM",
8750 "invalid transform enum");
8751 return error::kNoError;
8753 if (!surface_->ScheduleOverlayPlane(
8754 c.plane_z_order,
8755 transform,
8756 image,
8757 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8758 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8759 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8760 "glScheduleOverlayPlaneCHROMIUM",
8761 "failed to schedule overlay");
8763 return error::kNoError;
8766 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8767 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8768 const std::string& name_str) {
8769 if (!StringIsValidForGLES(name_str.c_str())) {
8770 LOCAL_SET_GL_ERROR(
8771 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8772 return error::kNoError;
8774 Program* program = GetProgramInfoNotShader(
8775 client_id, "glGetAttribLocation");
8776 if (!program) {
8777 return error::kNoError;
8779 if (!program->IsValid()) {
8780 LOCAL_SET_GL_ERROR(
8781 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8782 return error::kNoError;
8784 GLint* location = GetSharedMemoryAs<GLint*>(
8785 location_shm_id, location_shm_offset, sizeof(GLint));
8786 if (!location) {
8787 return error::kOutOfBounds;
8789 // Require the client to init this incase the context is lost and we are no
8790 // longer executing commands.
8791 if (*location != -1) {
8792 return error::kGenericError;
8794 *location = program->GetAttribLocation(name_str);
8795 return error::kNoError;
8798 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8799 uint32 immediate_data_size,
8800 const void* cmd_data) {
8801 const gles2::cmds::GetAttribLocation& c =
8802 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8803 Bucket* bucket = GetBucket(c.name_bucket_id);
8804 if (!bucket) {
8805 return error::kInvalidArguments;
8807 std::string name_str;
8808 if (!bucket->GetAsString(&name_str)) {
8809 return error::kInvalidArguments;
8811 return GetAttribLocationHelper(
8812 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8815 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8816 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8817 const std::string& name_str) {
8818 if (!StringIsValidForGLES(name_str.c_str())) {
8819 LOCAL_SET_GL_ERROR(
8820 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8821 return error::kNoError;
8823 Program* program = GetProgramInfoNotShader(
8824 client_id, "glGetUniformLocation");
8825 if (!program) {
8826 return error::kNoError;
8828 if (!program->IsValid()) {
8829 LOCAL_SET_GL_ERROR(
8830 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8831 return error::kNoError;
8833 GLint* location = GetSharedMemoryAs<GLint*>(
8834 location_shm_id, location_shm_offset, sizeof(GLint));
8835 if (!location) {
8836 return error::kOutOfBounds;
8838 // Require the client to init this incase the context is lost an we are no
8839 // longer executing commands.
8840 if (*location != -1) {
8841 return error::kGenericError;
8843 *location = program->GetUniformFakeLocation(name_str);
8844 return error::kNoError;
8847 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8848 uint32 immediate_data_size,
8849 const void* cmd_data) {
8850 const gles2::cmds::GetUniformLocation& c =
8851 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8852 Bucket* bucket = GetBucket(c.name_bucket_id);
8853 if (!bucket) {
8854 return error::kInvalidArguments;
8856 std::string name_str;
8857 if (!bucket->GetAsString(&name_str)) {
8858 return error::kInvalidArguments;
8860 return GetUniformLocationHelper(
8861 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8864 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8865 uint32 immediate_data_size,
8866 const void* cmd_data) {
8867 if (!unsafe_es3_apis_enabled())
8868 return error::kUnknownCommand;
8869 const gles2::cmds::GetUniformIndices& c =
8870 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8871 Bucket* bucket = GetBucket(c.names_bucket_id);
8872 if (!bucket) {
8873 return error::kInvalidArguments;
8875 GLsizei count = 0;
8876 std::vector<char*> names;
8877 std::vector<GLint> len;
8878 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8879 return error::kInvalidArguments;
8881 typedef cmds::GetUniformIndices::Result Result;
8882 Result* result = GetSharedMemoryAs<Result*>(
8883 c.indices_shm_id, c.indices_shm_offset,
8884 Result::ComputeSize(static_cast<size_t>(count)));
8885 GLuint* indices = result ? result->GetData() : NULL;
8886 if (indices == NULL) {
8887 return error::kOutOfBounds;
8889 // Check that the client initialized the result.
8890 if (result->size != 0) {
8891 return error::kInvalidArguments;
8893 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8894 if (!program) {
8895 return error::kNoError;
8897 GLuint service_id = program->service_id();
8898 GLint link_status = GL_FALSE;
8899 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8900 if (link_status != GL_TRUE) {
8901 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8902 "glGetUniformIndices", "program not linked");
8903 return error::kNoError;
8905 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8906 glGetUniformIndices(service_id, count, &names[0], indices);
8907 GLenum error = glGetError();
8908 if (error == GL_NO_ERROR) {
8909 result->SetNumResults(count);
8910 } else {
8911 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8913 return error::kNoError;
8916 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8917 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8918 const std::string& name_str) {
8919 GLint* location = GetSharedMemoryAs<GLint*>(
8920 location_shm_id, location_shm_offset, sizeof(GLint));
8921 if (!location) {
8922 return error::kOutOfBounds;
8924 // Require the client to init this incase the context is lost and we are no
8925 // longer executing commands.
8926 if (*location != -1) {
8927 return error::kGenericError;
8929 Program* program = GetProgramInfoNotShader(
8930 client_id, "glGetFragDataLocation");
8931 if (!program) {
8932 return error::kNoError;
8934 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8935 return error::kNoError;
8938 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8939 uint32 immediate_data_size,
8940 const void* cmd_data) {
8941 if (!unsafe_es3_apis_enabled())
8942 return error::kUnknownCommand;
8943 const gles2::cmds::GetFragDataLocation& c =
8944 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8945 Bucket* bucket = GetBucket(c.name_bucket_id);
8946 if (!bucket) {
8947 return error::kInvalidArguments;
8949 std::string name_str;
8950 if (!bucket->GetAsString(&name_str)) {
8951 return error::kInvalidArguments;
8953 return GetFragDataLocationHelper(
8954 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8957 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8958 uint32 immediate_data_size, const void* cmd_data) {
8959 if (!unsafe_es3_apis_enabled())
8960 return error::kUnknownCommand;
8961 const gles2::cmds::GetUniformBlockIndex& c =
8962 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8963 Bucket* bucket = GetBucket(c.name_bucket_id);
8964 if (!bucket) {
8965 return error::kInvalidArguments;
8967 std::string name_str;
8968 if (!bucket->GetAsString(&name_str)) {
8969 return error::kInvalidArguments;
8971 GLuint* index = GetSharedMemoryAs<GLuint*>(
8972 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8973 if (!index) {
8974 return error::kOutOfBounds;
8976 // Require the client to init this in case the context is lost and we are no
8977 // longer executing commands.
8978 if (*index != GL_INVALID_INDEX) {
8979 return error::kGenericError;
8981 Program* program = GetProgramInfoNotShader(
8982 c.program, "glGetUniformBlockIndex");
8983 if (!program) {
8984 return error::kNoError;
8986 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8987 return error::kNoError;
8990 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8991 const void* cmd_data) {
8992 const gles2::cmds::GetString& c =
8993 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8994 GLenum name = static_cast<GLenum>(c.name);
8995 if (!validators_->string_type.IsValid(name)) {
8996 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8997 return error::kNoError;
9000 const char* str = nullptr;
9001 std::string extensions;
9002 switch (name) {
9003 case GL_VERSION:
9004 if (unsafe_es3_apis_enabled())
9005 str = "OpenGL ES 3.0 Chromium";
9006 else
9007 str = "OpenGL ES 2.0 Chromium";
9008 break;
9009 case GL_SHADING_LANGUAGE_VERSION:
9010 if (unsafe_es3_apis_enabled())
9011 str = "OpenGL ES GLSL ES 3.0 Chromium";
9012 else
9013 str = "OpenGL ES GLSL ES 1.0 Chromium";
9014 break;
9015 case GL_RENDERER:
9016 case GL_VENDOR:
9017 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9018 // They are used by WEBGL_debug_renderer_info.
9019 if (!IsWebGLContext())
9020 str = "Chromium";
9021 else
9022 str = reinterpret_cast<const char*>(glGetString(name));
9023 break;
9024 case GL_EXTENSIONS:
9026 // For WebGL contexts, strip out the OES derivatives and
9027 // EXT frag depth extensions if they have not been enabled.
9028 if (IsWebGLContext()) {
9029 extensions = feature_info_->extensions();
9030 if (!derivatives_explicitly_enabled_) {
9031 size_t offset = extensions.find(kOESDerivativeExtension);
9032 if (std::string::npos != offset) {
9033 extensions.replace(offset, arraysize(kOESDerivativeExtension),
9034 std::string());
9037 if (!frag_depth_explicitly_enabled_) {
9038 size_t offset = extensions.find(kEXTFragDepthExtension);
9039 if (std::string::npos != offset) {
9040 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
9041 std::string());
9044 if (!draw_buffers_explicitly_enabled_) {
9045 size_t offset = extensions.find(kEXTDrawBuffersExtension);
9046 if (std::string::npos != offset) {
9047 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
9048 std::string());
9051 if (!shader_texture_lod_explicitly_enabled_) {
9052 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
9053 if (std::string::npos != offset) {
9054 extensions.replace(offset,
9055 arraysize(kEXTShaderTextureLodExtension),
9056 std::string());
9059 } else {
9060 extensions = feature_info_->extensions().c_str();
9062 if (supports_post_sub_buffer_)
9063 extensions += " GL_CHROMIUM_post_sub_buffer";
9064 str = extensions.c_str();
9066 break;
9067 default:
9068 str = reinterpret_cast<const char*>(glGetString(name));
9069 break;
9071 Bucket* bucket = CreateBucket(c.bucket_id);
9072 bucket->SetFromString(str);
9073 return error::kNoError;
9076 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9077 const void* cmd_data) {
9078 const gles2::cmds::BufferData& c =
9079 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9080 GLenum target = static_cast<GLenum>(c.target);
9081 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9082 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9083 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9084 GLenum usage = static_cast<GLenum>(c.usage);
9085 const void* data = NULL;
9086 if (data_shm_id != 0 || data_shm_offset != 0) {
9087 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9088 if (!data) {
9089 return error::kOutOfBounds;
9092 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9093 return error::kNoError;
9096 void GLES2DecoderImpl::DoBufferSubData(
9097 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9098 // Just delegate it. Some validation is actually done before this.
9099 buffer_manager()->ValidateAndDoBufferSubData(
9100 &state_, target, offset, size, data);
9103 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9104 unsigned target,
9105 int level,
9106 unsigned format,
9107 unsigned type,
9108 int xoffset,
9109 int yoffset,
9110 int width,
9111 int height) {
9112 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9113 if ((feature_info_->feature_flags().angle_depth_texture ||
9114 feature_info_->IsES3Enabled())
9115 && (channels & GLES2Util::kDepth) != 0) {
9116 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9117 // on depth formats.
9118 GLuint fb = 0;
9119 glGenFramebuffersEXT(1, &fb);
9120 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9122 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9123 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9124 GL_DEPTH_ATTACHMENT;
9126 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9127 texture->service_id(), level);
9128 // ANGLE promises a depth only attachment ok.
9129 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9130 GL_FRAMEBUFFER_COMPLETE) {
9131 return false;
9133 glClearStencil(0);
9134 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9135 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9136 glClearDepth(1.0f);
9137 state_.SetDeviceDepthMask(GL_TRUE);
9138 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9139 glScissor(xoffset, yoffset, width, height);
9140 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9142 RestoreClearState();
9144 glDeleteFramebuffersEXT(1, &fb);
9145 Framebuffer* framebuffer =
9146 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9147 GLuint fb_service_id =
9148 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9149 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9150 return true;
9153 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9155 uint32 size;
9156 uint32 padded_row_size;
9157 if (!GLES2Util::ComputeImageDataSizes(
9158 width, height, 1, format, type, state_.unpack_alignment, &size,
9159 NULL, &padded_row_size)) {
9160 return false;
9163 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9165 int tile_height;
9167 if (size > kMaxZeroSize) {
9168 if (kMaxZeroSize < padded_row_size) {
9169 // That'd be an awfully large texture.
9170 return false;
9172 // We should never have a large total size with a zero row size.
9173 DCHECK_GT(padded_row_size, 0U);
9174 tile_height = kMaxZeroSize / padded_row_size;
9175 if (!GLES2Util::ComputeImageDataSizes(
9176 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9177 NULL, NULL)) {
9178 return false;
9180 } else {
9181 tile_height = height;
9184 // Assumes the size has already been checked.
9185 scoped_ptr<char[]> zero(new char[size]);
9186 memset(zero.get(), 0, size);
9187 glBindTexture(texture->target(), texture->service_id());
9189 GLint y = 0;
9190 while (y < height) {
9191 GLint h = y + tile_height > height ? height - y : tile_height;
9192 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9193 zero.get());
9194 y += tile_height;
9196 TextureRef* bound_texture =
9197 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9198 glBindTexture(texture->target(),
9199 bound_texture ? bound_texture->service_id() : 0);
9200 return true;
9203 namespace {
9205 const int kS3TCBlockWidth = 4;
9206 const int kS3TCBlockHeight = 4;
9207 const int kS3TCDXT1BlockSize = 8;
9208 const int kS3TCDXT3AndDXT5BlockSize = 16;
9209 const int kEACAndETC2BlockSize = 4;
9211 bool IsValidDXTSize(GLint level, GLsizei size) {
9212 return (size == 1) ||
9213 (size == 2) || !(size % kS3TCBlockWidth);
9216 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9217 return GLES2Util::IsPOT(size);
9220 } // anonymous namespace.
9222 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9223 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9224 GLenum format, GLsizei* size_in_bytes) {
9225 base::CheckedNumeric<GLsizei> bytes_required(0);
9227 switch (format) {
9228 case GL_ATC_RGB_AMD:
9229 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9230 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9231 case GL_ETC1_RGB8_OES:
9232 bytes_required =
9233 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9234 bytes_required *=
9235 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9236 bytes_required *= kS3TCDXT1BlockSize;
9237 break;
9238 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9239 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9240 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9241 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9242 bytes_required =
9243 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9244 bytes_required *=
9245 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9246 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9247 break;
9248 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9249 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9250 bytes_required = std::max(width, 8);
9251 bytes_required *= std::max(height, 8);
9252 bytes_required *= 4;
9253 bytes_required += 7;
9254 bytes_required /= 8;
9255 break;
9256 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9257 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9258 bytes_required = std::max(width, 16);
9259 bytes_required *= std::max(height, 8);
9260 bytes_required *= 2;
9261 bytes_required += 7;
9262 bytes_required /= 8;
9263 break;
9265 // ES3 formats.
9266 case GL_COMPRESSED_R11_EAC:
9267 case GL_COMPRESSED_SIGNED_R11_EAC:
9268 case GL_COMPRESSED_RGB8_ETC2:
9269 case GL_COMPRESSED_SRGB8_ETC2:
9270 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9271 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9272 bytes_required =
9273 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9274 bytes_required *=
9275 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9276 bytes_required *= 8;
9277 bytes_required *= depth;
9278 break;
9279 case GL_COMPRESSED_RG11_EAC:
9280 case GL_COMPRESSED_SIGNED_RG11_EAC:
9281 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9282 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9283 bytes_required =
9284 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9285 bytes_required *=
9286 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9287 bytes_required *= 16;
9288 bytes_required *= depth;
9289 break;
9290 default:
9291 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9292 return false;
9295 if (!bytes_required.IsValid()) {
9296 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9297 return false;
9300 *size_in_bytes = bytes_required.ValueOrDefault(0);
9301 return true;
9304 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9305 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9306 GLenum format, GLsizei size) {
9307 GLsizei bytes_required = 0;
9308 if (!GetCompressedTexSizeInBytes(
9309 function_name, width, height, depth, format, &bytes_required)) {
9310 return false;
9313 if (size != bytes_required) {
9314 LOCAL_SET_GL_ERROR(
9315 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9316 return false;
9319 return true;
9322 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9323 const char* function_name, GLenum target, GLint level,
9324 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9325 switch (format) {
9326 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9327 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9328 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9329 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9330 DCHECK_EQ(1, depth); // 2D formats.
9331 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9332 LOCAL_SET_GL_ERROR(
9333 GL_INVALID_OPERATION, function_name,
9334 "width or height invalid for level");
9335 return false;
9337 return true;
9338 case GL_ATC_RGB_AMD:
9339 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9340 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9341 case GL_ETC1_RGB8_OES:
9342 DCHECK_EQ(1, depth); // 2D formats.
9343 if (width <= 0 || height <= 0) {
9344 LOCAL_SET_GL_ERROR(
9345 GL_INVALID_OPERATION, function_name,
9346 "width or height invalid for level");
9347 return false;
9349 return true;
9350 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9351 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9352 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9353 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9354 DCHECK_EQ(1, depth); // 2D formats.
9355 if (!IsValidPVRTCSize(level, width) ||
9356 !IsValidPVRTCSize(level, height)) {
9357 LOCAL_SET_GL_ERROR(
9358 GL_INVALID_OPERATION, function_name,
9359 "width or height invalid for level");
9360 return false;
9362 return true;
9364 // ES3 formats.
9365 case GL_COMPRESSED_R11_EAC:
9366 case GL_COMPRESSED_SIGNED_R11_EAC:
9367 case GL_COMPRESSED_RG11_EAC:
9368 case GL_COMPRESSED_SIGNED_RG11_EAC:
9369 case GL_COMPRESSED_RGB8_ETC2:
9370 case GL_COMPRESSED_SRGB8_ETC2:
9371 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9372 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9373 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9374 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9375 if (width <= 0 || height <= 0 || depth <= 0) {
9376 LOCAL_SET_GL_ERROR(
9377 GL_INVALID_OPERATION, function_name,
9378 "width, height, or depth invalid");
9379 return false;
9381 if (target == GL_TEXTURE_3D) {
9382 LOCAL_SET_GL_ERROR(
9383 GL_INVALID_OPERATION, function_name,
9384 "target invalid for format");
9385 return false;
9387 return true;
9388 default:
9389 return false;
9393 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9394 const char* function_name,
9395 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9396 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9397 Texture* texture) {
9398 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9399 LOCAL_SET_GL_ERROR(
9400 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9401 return false;
9404 switch (format) {
9405 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9406 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9407 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9408 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9409 const int kBlockWidth = 4;
9410 const int kBlockHeight = 4;
9411 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9412 LOCAL_SET_GL_ERROR(
9413 GL_INVALID_OPERATION, function_name,
9414 "xoffset or yoffset not multiple of 4");
9415 return false;
9417 GLsizei tex_width = 0;
9418 GLsizei tex_height = 0;
9419 if (!texture->GetLevelSize(target, level,
9420 &tex_width, &tex_height, nullptr) ||
9421 width - xoffset > tex_width ||
9422 height - yoffset > tex_height) {
9423 LOCAL_SET_GL_ERROR(
9424 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9425 return false;
9427 return ValidateCompressedTexDimensions(
9428 function_name, target, level, width, height, 1, format);
9430 case GL_ATC_RGB_AMD:
9431 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9432 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9433 LOCAL_SET_GL_ERROR(
9434 GL_INVALID_OPERATION, function_name,
9435 "not supported for ATC textures");
9436 return false;
9438 case GL_ETC1_RGB8_OES: {
9439 LOCAL_SET_GL_ERROR(
9440 GL_INVALID_OPERATION, function_name,
9441 "not supported for ECT1_RGB8_OES textures");
9442 return false;
9444 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9445 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9446 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9447 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9448 if ((xoffset != 0) || (yoffset != 0)) {
9449 LOCAL_SET_GL_ERROR(
9450 GL_INVALID_OPERATION, function_name,
9451 "xoffset and yoffset must be zero");
9452 return false;
9454 GLsizei tex_width = 0;
9455 GLsizei tex_height = 0;
9456 if (!texture->GetLevelSize(target, level,
9457 &tex_width, &tex_height, nullptr) ||
9458 width != tex_width ||
9459 height != tex_height) {
9460 LOCAL_SET_GL_ERROR(
9461 GL_INVALID_OPERATION, function_name,
9462 "dimensions must match existing texture level dimensions");
9463 return false;
9465 return ValidateCompressedTexDimensions(
9466 function_name, target, level, width, height, 1, format);
9469 // ES3 formats
9470 case GL_COMPRESSED_R11_EAC:
9471 case GL_COMPRESSED_SIGNED_R11_EAC:
9472 case GL_COMPRESSED_RG11_EAC:
9473 case GL_COMPRESSED_SIGNED_RG11_EAC:
9474 case GL_COMPRESSED_RGB8_ETC2:
9475 case GL_COMPRESSED_SRGB8_ETC2:
9476 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9477 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9478 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9479 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9481 const int kBlockSize = 4;
9482 GLsizei tex_width, tex_height;
9483 if (target == GL_TEXTURE_3D ||
9484 !texture->GetLevelSize(target, level,
9485 &tex_width, &tex_height, nullptr) ||
9486 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9487 ((width % kBlockSize) && xoffset + width != tex_width) ||
9488 ((height % kBlockSize) && yoffset + height != tex_height)) {
9489 LOCAL_SET_GL_ERROR(
9490 GL_INVALID_OPERATION, function_name,
9491 "dimensions must match existing texture level dimensions");
9492 return false;
9494 return true;
9496 default:
9497 return false;
9501 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9502 GLenum target,
9503 GLint level,
9504 GLenum internal_format,
9505 GLsizei width,
9506 GLsizei height,
9507 GLint border,
9508 GLsizei image_size,
9509 const void* data) {
9510 if (!validators_->texture_target.IsValid(target)) {
9511 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9512 "glCompressedTexImage2D", target, "target");
9513 return error::kNoError;
9515 if (!validators_->compressed_texture_format.IsValid(
9516 internal_format)) {
9517 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9518 "glCompressedTexImage2D", internal_format, "internal_format");
9519 return error::kNoError;
9521 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9522 border != 0) {
9523 LOCAL_SET_GL_ERROR(
9524 GL_INVALID_VALUE,
9525 "glCompressedTexImage2D", "dimensions out of range");
9526 return error::kNoError;
9528 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9529 &state_, target);
9530 if (!texture_ref) {
9531 LOCAL_SET_GL_ERROR(
9532 GL_INVALID_VALUE,
9533 "glCompressedTexImage2D", "unknown texture target");
9534 return error::kNoError;
9536 Texture* texture = texture_ref->texture();
9537 if (texture->IsImmutable()) {
9538 LOCAL_SET_GL_ERROR(
9539 GL_INVALID_OPERATION,
9540 "glCompressedTexImage2D", "texture is immutable");
9541 return error::kNoError;
9544 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9545 width, height, 1, internal_format) ||
9546 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9547 1, internal_format, image_size)) {
9548 return error::kNoError;
9551 if (!EnsureGPUMemoryAvailable(image_size)) {
9552 LOCAL_SET_GL_ERROR(
9553 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9554 return error::kNoError;
9557 if (texture->IsAttachedToFramebuffer()) {
9558 framebuffer_state_.clear_state_dirty = true;
9561 scoped_ptr<int8[]> zero;
9562 if (!data) {
9563 zero.reset(new int8[image_size]);
9564 memset(zero.get(), 0, image_size);
9565 data = zero.get();
9567 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9568 glCompressedTexImage2D(
9569 target, level, internal_format, width, height, border, image_size, data);
9570 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9571 if (error == GL_NO_ERROR) {
9572 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9573 width, height, 1, border, 0, 0,
9574 gfx::Rect(width, height));
9577 // This may be a slow command. Exit command processing to allow for
9578 // context preemption and GPU watchdog checks.
9579 ExitCommandProcessingEarly();
9580 return error::kNoError;
9583 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9584 uint32 immediate_data_size,
9585 const void* cmd_data) {
9586 const gles2::cmds::CompressedTexImage2D& c =
9587 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9588 GLenum target = static_cast<GLenum>(c.target);
9589 GLint level = static_cast<GLint>(c.level);
9590 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9591 GLsizei width = static_cast<GLsizei>(c.width);
9592 GLsizei height = static_cast<GLsizei>(c.height);
9593 GLint border = static_cast<GLint>(c.border);
9594 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9595 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9596 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9597 const void* data = NULL;
9598 if (data_shm_id != 0 || data_shm_offset != 0) {
9599 data = GetSharedMemoryAs<const void*>(
9600 data_shm_id, data_shm_offset, image_size);
9601 if (!data) {
9602 return error::kOutOfBounds;
9605 return DoCompressedTexImage2D(
9606 target, level, internal_format, width, height, border, image_size, data);
9609 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9610 uint32 immediate_data_size,
9611 const void* cmd_data) {
9612 const gles2::cmds::CompressedTexImage2DBucket& c =
9613 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9614 GLenum target = static_cast<GLenum>(c.target);
9615 GLint level = static_cast<GLint>(c.level);
9616 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9617 GLsizei width = static_cast<GLsizei>(c.width);
9618 GLsizei height = static_cast<GLsizei>(c.height);
9619 GLint border = static_cast<GLint>(c.border);
9620 Bucket* bucket = GetBucket(c.bucket_id);
9621 if (!bucket) {
9622 return error::kInvalidArguments;
9624 uint32 data_size = bucket->size();
9625 GLsizei imageSize = data_size;
9626 const void* data = bucket->GetData(0, data_size);
9627 if (!data) {
9628 return error::kInvalidArguments;
9630 return DoCompressedTexImage2D(
9631 target, level, internal_format, width, height, border,
9632 imageSize, data);
9635 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9636 uint32 immediate_data_size,
9637 const void* cmd_data) {
9638 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9639 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9640 GLenum target = static_cast<GLenum>(c.target);
9641 GLint level = static_cast<GLint>(c.level);
9642 GLint xoffset = static_cast<GLint>(c.xoffset);
9643 GLint yoffset = static_cast<GLint>(c.yoffset);
9644 GLsizei width = static_cast<GLsizei>(c.width);
9645 GLsizei height = static_cast<GLsizei>(c.height);
9646 GLenum format = static_cast<GLenum>(c.format);
9647 Bucket* bucket = GetBucket(c.bucket_id);
9648 if (!bucket) {
9649 return error::kInvalidArguments;
9651 uint32 data_size = bucket->size();
9652 GLsizei imageSize = data_size;
9653 const void* data = bucket->GetData(0, data_size);
9654 if (!data) {
9655 return error::kInvalidArguments;
9657 if (!validators_->texture_target.IsValid(target)) {
9658 LOCAL_SET_GL_ERROR(
9659 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9660 return error::kNoError;
9662 if (!validators_->compressed_texture_format.IsValid(format)) {
9663 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9664 "glCompressedTexSubImage2D", format, "format");
9665 return error::kNoError;
9667 if (width < 0) {
9668 LOCAL_SET_GL_ERROR(
9669 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9670 return error::kNoError;
9672 if (height < 0) {
9673 LOCAL_SET_GL_ERROR(
9674 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9675 return error::kNoError;
9677 if (imageSize < 0) {
9678 LOCAL_SET_GL_ERROR(
9679 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9680 return error::kNoError;
9682 DoCompressedTexSubImage2D(
9683 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9684 return error::kNoError;
9687 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9688 GLenum target,
9689 GLint level,
9690 GLenum internal_format,
9691 GLsizei width,
9692 GLsizei height,
9693 GLsizei depth,
9694 GLint border,
9695 GLsizei image_size,
9696 const void* data) {
9697 if (!validators_->texture_3_d_target.IsValid(target)) {
9698 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9699 "glCompressedTexImage3D", target, "target");
9700 return error::kNoError;
9702 if (!validators_->compressed_texture_format.IsValid(
9703 internal_format)) {
9704 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9705 "glCompressedTexImage3D", internal_format, "internal_format");
9706 return error::kNoError;
9708 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9709 border != 0) {
9710 LOCAL_SET_GL_ERROR(
9711 GL_INVALID_VALUE,
9712 "glCompressedTexImage3D", "dimensions out of range");
9713 return error::kNoError;
9715 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9716 &state_, target);
9717 if (!texture_ref) {
9718 LOCAL_SET_GL_ERROR(
9719 GL_INVALID_VALUE,
9720 "glCompressedTexImage3D", "unknown texture target");
9721 return error::kNoError;
9723 Texture* texture = texture_ref->texture();
9724 if (texture->IsImmutable()) {
9725 LOCAL_SET_GL_ERROR(
9726 GL_INVALID_OPERATION,
9727 "glCompressedTexImage3D", "texture is immutable");
9728 return error::kNoError;
9731 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9732 width, height, depth, internal_format) ||
9733 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9734 depth, internal_format, image_size)) {
9735 return error::kNoError;
9738 if (!EnsureGPUMemoryAvailable(image_size)) {
9739 LOCAL_SET_GL_ERROR(
9740 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9741 return error::kNoError;
9744 if (texture->IsAttachedToFramebuffer()) {
9745 framebuffer_state_.clear_state_dirty = true;
9748 scoped_ptr<int8[]> zero;
9749 if (!data) {
9750 zero.reset(new int8[image_size]);
9751 memset(zero.get(), 0, image_size);
9752 data = zero.get();
9754 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9755 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9756 border, image_size, data);
9757 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9758 if (error == GL_NO_ERROR) {
9759 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9760 width, height, depth, border, 0, 0,
9761 gfx::Rect(width, height));
9764 // This may be a slow command. Exit command processing to allow for
9765 // context preemption and GPU watchdog checks.
9766 ExitCommandProcessingEarly();
9767 return error::kNoError;
9770 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9771 uint32 immediate_data_size, const void* cmd_data) {
9772 if (!unsafe_es3_apis_enabled())
9773 return error::kUnknownCommand;
9775 const gles2::cmds::CompressedTexImage3D& c =
9776 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9777 GLenum target = static_cast<GLenum>(c.target);
9778 GLint level = static_cast<GLint>(c.level);
9779 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9780 GLsizei width = static_cast<GLsizei>(c.width);
9781 GLsizei height = static_cast<GLsizei>(c.height);
9782 GLsizei depth = static_cast<GLsizei>(c.depth);
9783 GLint border = static_cast<GLint>(c.border);
9784 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9785 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9786 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9787 const void* data = NULL;
9788 if (data_shm_id != 0 || data_shm_offset != 0) {
9789 data = GetSharedMemoryAs<const void*>(
9790 data_shm_id, data_shm_offset, image_size);
9791 if (!data) {
9792 return error::kOutOfBounds;
9795 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9796 depth, border, image_size, data);
9799 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9800 uint32 immediate_data_size, const void* cmd_data) {
9801 if (!unsafe_es3_apis_enabled())
9802 return error::kUnknownCommand;
9804 const gles2::cmds::CompressedTexImage3DBucket& c =
9805 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9806 GLenum target = static_cast<GLenum>(c.target);
9807 GLint level = static_cast<GLint>(c.level);
9808 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9809 GLsizei width = static_cast<GLsizei>(c.width);
9810 GLsizei height = static_cast<GLsizei>(c.height);
9811 GLsizei depth = static_cast<GLsizei>(c.depth);
9812 GLint border = static_cast<GLint>(c.border);
9813 Bucket* bucket = GetBucket(c.bucket_id);
9814 if (!bucket) {
9815 return error::kInvalidArguments;
9817 uint32 data_size = bucket->size();
9818 GLsizei imageSize = data_size;
9819 const void* data = bucket->GetData(0, data_size);
9820 if (!data) {
9821 return error::kInvalidArguments;
9823 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9824 depth, border, imageSize, data);
9827 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9828 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9829 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9830 GLsizei image_size, const void* data) {
9831 if (!validators_->texture_3_d_target.IsValid(target)) {
9832 LOCAL_SET_GL_ERROR(
9833 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9834 return;
9836 if (!validators_->compressed_texture_format.IsValid(format)) {
9837 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9838 "glCompressedTexSubImage3D", format, "format");
9839 return;
9841 if (width < 0 || height < 0 || depth < 0) {
9842 LOCAL_SET_GL_ERROR(
9843 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9844 return;
9846 if (image_size < 0) {
9847 LOCAL_SET_GL_ERROR(
9848 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9849 return;
9851 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9852 &state_, target);
9853 if (!texture_ref) {
9854 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9855 "unknown texture for target");
9856 return;
9858 Texture* texture = texture_ref->texture();
9859 GLenum type = 0, internal_format = 0;
9860 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9861 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9862 "level does not exist");
9863 return;
9865 if (internal_format != format) {
9866 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9867 "format does not match internal format");
9868 return;
9870 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9871 width, height, depth, type)) {
9872 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9873 "bad dimensions");
9874 return;
9876 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9877 width, height, depth, format,
9878 image_size) ||
9879 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9880 target, level, xoffset, yoffset,
9881 zoffset, width, height, depth,
9882 format, texture)) {
9883 return;
9886 // Note: There is no need to deal with texture cleared tracking here
9887 // because the validation above means you can only get here if the level
9888 // is already a matching compressed format and in that case
9889 // CompressedTexImage3D already cleared the texture.
9890 glCompressedTexSubImage3D(
9891 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9892 image_size, data);
9894 // This may be a slow command. Exit command processing to allow for
9895 // context preemption and GPU watchdog checks.
9896 ExitCommandProcessingEarly();
9899 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9900 uint32 immediate_data_size, const void* cmd_data) {
9901 if (!unsafe_es3_apis_enabled())
9902 return error::kUnknownCommand;
9903 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9904 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9905 GLenum target = static_cast<GLenum>(c.target);
9906 GLint level = static_cast<GLint>(c.level);
9907 GLint xoffset = static_cast<GLint>(c.xoffset);
9908 GLint yoffset = static_cast<GLint>(c.yoffset);
9909 GLint zoffset = static_cast<GLint>(c.zoffset);
9910 GLsizei width = static_cast<GLsizei>(c.width);
9911 GLsizei height = static_cast<GLsizei>(c.height);
9912 GLsizei depth = static_cast<GLsizei>(c.depth);
9913 GLenum format = static_cast<GLenum>(c.format);
9914 Bucket* bucket = GetBucket(c.bucket_id);
9915 if (!bucket) {
9916 return error::kInvalidArguments;
9918 uint32 data_size = bucket->size();
9919 GLsizei image_size = data_size;
9920 const void* data = bucket->GetData(0, data_size);
9921 if (!data) {
9922 return error::kInvalidArguments;
9924 DoCompressedTexSubImage3D(
9925 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9926 image_size, data);
9927 return error::kNoError;
9930 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9931 const void* cmd_data) {
9932 const gles2::cmds::TexImage2D& c =
9933 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9934 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9935 "width", c.width, "height", c.height);
9936 // Set as failed for now, but if it successed, this will be set to not failed.
9937 texture_state_.tex_image_failed = true;
9938 GLenum target = static_cast<GLenum>(c.target);
9939 GLint level = static_cast<GLint>(c.level);
9940 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9941 // for internalformat.
9942 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9943 GLsizei width = static_cast<GLsizei>(c.width);
9944 GLsizei height = static_cast<GLsizei>(c.height);
9945 GLint border = static_cast<GLint>(c.border);
9946 GLenum format = static_cast<GLenum>(c.format);
9947 GLenum type = static_cast<GLenum>(c.type);
9948 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9949 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9950 uint32 pixels_size;
9951 if (!GLES2Util::ComputeImageDataSizes(
9952 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9953 NULL, NULL)) {
9954 return error::kOutOfBounds;
9956 const void* pixels = NULL;
9957 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9958 pixels = GetSharedMemoryAs<const void*>(
9959 pixels_shm_id, pixels_shm_offset, pixels_size);
9960 if (!pixels) {
9961 return error::kOutOfBounds;
9965 // For testing only. Allows us to stress the ability to respond to OOM errors.
9966 if (workarounds().simulate_out_of_memory_on_large_textures &&
9967 (width * height >= 4096 * 4096)) {
9968 LOCAL_SET_GL_ERROR(
9969 GL_OUT_OF_MEMORY,
9970 "glTexImage2D", "synthetic out of memory");
9971 return error::kNoError;
9974 TextureManager::DoTexImageArguments args = {
9975 target, level, internal_format, width, height, 1, border, format, type,
9976 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9977 texture_manager()->ValidateAndDoTexImage(
9978 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9980 // This may be a slow command. Exit command processing to allow for
9981 // context preemption and GPU watchdog checks.
9982 ExitCommandProcessingEarly();
9983 return error::kNoError;
9986 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9987 const void* cmd_data) {
9988 if (!unsafe_es3_apis_enabled())
9989 return error::kUnknownCommand;
9991 const gles2::cmds::TexImage3D& c =
9992 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9993 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9994 "widthXheight", c.width * c.height, "depth", c.depth);
9995 // Set as failed for now, but if it successed, this will be set to not failed.
9996 texture_state_.tex_image_failed = true;
9997 GLenum target = static_cast<GLenum>(c.target);
9998 GLint level = static_cast<GLint>(c.level);
9999 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10000 GLsizei width = static_cast<GLsizei>(c.width);
10001 GLsizei height = static_cast<GLsizei>(c.height);
10002 GLsizei depth = static_cast<GLsizei>(c.depth);
10003 GLint border = static_cast<GLint>(c.border);
10004 GLenum format = static_cast<GLenum>(c.format);
10005 GLenum type = static_cast<GLenum>(c.type);
10006 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10007 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10008 uint32 pixels_size;
10009 if (!GLES2Util::ComputeImageDataSizes(
10010 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
10011 NULL, NULL)) {
10012 return error::kOutOfBounds;
10014 const void* pixels = NULL;
10015 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10016 pixels = GetSharedMemoryAs<const void*>(
10017 pixels_shm_id, pixels_shm_offset, pixels_size);
10018 if (!pixels) {
10019 return error::kOutOfBounds;
10023 // For testing only. Allows us to stress the ability to respond to OOM errors.
10024 if (workarounds().simulate_out_of_memory_on_large_textures &&
10025 (width * height * depth >= 4096 * 4096)) {
10026 LOCAL_SET_GL_ERROR(
10027 GL_OUT_OF_MEMORY,
10028 "glTexImage3D", "synthetic out of memory");
10029 return error::kNoError;
10032 TextureManager::DoTexImageArguments args = {
10033 target, level, internal_format, width, height, depth, border, format, type,
10034 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
10035 texture_manager()->ValidateAndDoTexImage(
10036 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
10038 // This may be a slow command. Exit command processing to allow for
10039 // context preemption and GPU watchdog checks.
10040 ExitCommandProcessingEarly();
10041 return error::kNoError;
10044 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10045 GLenum target,
10046 GLint level,
10047 GLint xoffset,
10048 GLint yoffset,
10049 GLsizei width,
10050 GLsizei height,
10051 GLenum format,
10052 GLsizei image_size,
10053 const void * data) {
10054 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10055 &state_, target);
10056 if (!texture_ref) {
10057 LOCAL_SET_GL_ERROR(
10058 GL_INVALID_OPERATION,
10059 "glCompressedTexSubImage2D", "unknown texture for target");
10060 return;
10062 Texture* texture = texture_ref->texture();
10063 GLenum type = 0;
10064 GLenum internal_format = 0;
10065 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10066 LOCAL_SET_GL_ERROR(
10067 GL_INVALID_OPERATION,
10068 "glCompressedTexSubImage2D", "level does not exist.");
10069 return;
10071 if (internal_format != format) {
10072 LOCAL_SET_GL_ERROR(
10073 GL_INVALID_OPERATION,
10074 "glCompressedTexSubImage2D", "format does not match internal format.");
10075 return;
10077 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10078 height, 1, type)) {
10079 LOCAL_SET_GL_ERROR(
10080 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10081 return;
10084 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10085 width, height, 1, format, image_size) ||
10086 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10087 target, level, xoffset, yoffset, 0,
10088 width, height, 1, format, texture)) {
10089 return;
10093 // Note: There is no need to deal with texture cleared tracking here
10094 // because the validation above means you can only get here if the level
10095 // is already a matching compressed format and in that case
10096 // CompressedTexImage2D already cleared the texture.
10097 glCompressedTexSubImage2D(
10098 target, level, xoffset, yoffset, width, height, format, image_size, data);
10100 // This may be a slow command. Exit command processing to allow for
10101 // context preemption and GPU watchdog checks.
10102 ExitCommandProcessingEarly();
10105 static void Clip(
10106 GLint start, GLint range, GLint sourceRange,
10107 GLint* out_start, GLint* out_range) {
10108 DCHECK(out_start);
10109 DCHECK(out_range);
10110 if (start < 0) {
10111 range += start;
10112 start = 0;
10114 GLint end = start + range;
10115 if (end > sourceRange) {
10116 range -= end - sourceRange;
10118 *out_start = start;
10119 *out_range = range;
10122 void GLES2DecoderImpl::DoCopyTexImage2D(
10123 GLenum target,
10124 GLint level,
10125 GLenum internal_format,
10126 GLint x,
10127 GLint y,
10128 GLsizei width,
10129 GLsizei height,
10130 GLint border) {
10131 DCHECK(!ShouldDeferReads());
10132 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10133 &state_, target);
10134 if (!texture_ref) {
10135 LOCAL_SET_GL_ERROR(
10136 GL_INVALID_OPERATION,
10137 "glCopyTexImage2D", "unknown texture for target");
10138 return;
10140 Texture* texture = texture_ref->texture();
10141 if (texture->IsImmutable()) {
10142 LOCAL_SET_GL_ERROR(
10143 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10144 return;
10146 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10147 border != 0) {
10148 LOCAL_SET_GL_ERROR(
10149 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10150 return;
10152 if (!texture_manager()->ValidateFormatAndTypeCombination(
10153 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10154 GL_UNSIGNED_BYTE)) {
10155 return;
10158 // Check we have compatible formats.
10159 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10160 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10161 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10163 if ((channels_needed & channels_exist) != channels_needed) {
10164 LOCAL_SET_GL_ERROR(
10165 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10166 return;
10169 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10170 LOCAL_SET_GL_ERROR(
10171 GL_INVALID_OPERATION,
10172 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10173 return;
10176 uint32 estimated_size = 0;
10177 if (!GLES2Util::ComputeImageDataSizes(
10178 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10179 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10180 LOCAL_SET_GL_ERROR(
10181 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10182 return;
10185 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10186 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10187 return;
10190 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10191 return;
10194 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10195 LOCAL_SET_GL_ERROR(
10196 GL_INVALID_OPERATION,
10197 "glCopyTexImage2D", "source and destination textures are the same");
10198 return;
10201 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10202 return;
10205 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10206 ScopedResolvedFrameBufferBinder binder(this, false, true);
10207 gfx::Size size = GetBoundReadFrameBufferSize();
10209 if (texture->IsAttachedToFramebuffer()) {
10210 framebuffer_state_.clear_state_dirty = true;
10213 // Clip to size to source dimensions
10214 GLint copyX = 0;
10215 GLint copyY = 0;
10216 GLint copyWidth = 0;
10217 GLint copyHeight = 0;
10218 Clip(x, width, size.width(), &copyX, &copyWidth);
10219 Clip(y, height, size.height(), &copyY, &copyHeight);
10221 if (copyX != x ||
10222 copyY != y ||
10223 copyWidth != width ||
10224 copyHeight != height) {
10225 // some part was clipped so clear the rect.
10226 uint32 pixels_size = 0;
10227 if (!GLES2Util::ComputeImageDataSizes(
10228 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10229 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10230 LOCAL_SET_GL_ERROR(
10231 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10232 return;
10234 scoped_ptr<char[]> zero(new char[pixels_size]);
10235 memset(zero.get(), 0, pixels_size);
10236 ScopedModifyPixels modify(texture_ref);
10237 glTexImage2D(target, level, internal_format, width, height, border,
10238 internal_format, GL_UNSIGNED_BYTE, zero.get());
10239 if (copyHeight > 0 && copyWidth > 0) {
10240 GLint dx = copyX - x;
10241 GLint dy = copyY - y;
10242 GLint destX = dx;
10243 GLint destY = dy;
10244 glCopyTexSubImage2D(target, level,
10245 destX, destY, copyX, copyY,
10246 copyWidth, copyHeight);
10248 } else {
10249 ScopedModifyPixels modify(texture_ref);
10250 glCopyTexImage2D(target, level, internal_format,
10251 copyX, copyY, copyWidth, copyHeight, border);
10253 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10254 if (error == GL_NO_ERROR) {
10255 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10256 width, height, 1, border, internal_format,
10257 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10260 // This may be a slow command. Exit command processing to allow for
10261 // context preemption and GPU watchdog checks.
10262 ExitCommandProcessingEarly();
10265 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10266 GLenum target,
10267 GLint level,
10268 GLint xoffset,
10269 GLint yoffset,
10270 GLint x,
10271 GLint y,
10272 GLsizei width,
10273 GLsizei height) {
10274 DCHECK(!ShouldDeferReads());
10275 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10276 &state_, target);
10277 if (!texture_ref) {
10278 LOCAL_SET_GL_ERROR(
10279 GL_INVALID_OPERATION,
10280 "glCopyTexSubImage2D", "unknown texture for target");
10281 return;
10283 Texture* texture = texture_ref->texture();
10284 GLenum type = 0;
10285 GLenum format = 0;
10286 if (!texture->GetLevelType(target, level, &type, &format) ||
10287 !texture->ValidForTexture(
10288 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10289 LOCAL_SET_GL_ERROR(
10290 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10291 return;
10293 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10294 LOCAL_SET_GL_ERROR(
10295 GL_INVALID_OPERATION,
10296 "glCopyTexSubImage2D", "async upload pending for texture");
10297 return;
10300 // Check we have compatible formats.
10301 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10302 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10303 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10305 if (!channels_needed ||
10306 (channels_needed & channels_exist) != channels_needed) {
10307 LOCAL_SET_GL_ERROR(
10308 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10309 return;
10312 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10313 LOCAL_SET_GL_ERROR(
10314 GL_INVALID_OPERATION,
10315 "glCopySubImage2D", "can not be used with depth or stencil textures");
10316 return;
10319 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10320 return;
10323 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10324 LOCAL_SET_GL_ERROR(
10325 GL_INVALID_OPERATION,
10326 "glCopyTexSubImage2D", "source and destination textures are the same");
10327 return;
10330 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10331 return;
10334 ScopedResolvedFrameBufferBinder binder(this, false, true);
10335 gfx::Size size = GetBoundReadFrameBufferSize();
10336 GLint copyX = 0;
10337 GLint copyY = 0;
10338 GLint copyWidth = 0;
10339 GLint copyHeight = 0;
10340 Clip(x, width, size.width(), &copyX, &copyWidth);
10341 Clip(y, height, size.height(), &copyY, &copyHeight);
10343 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10344 height != size.height()) {
10345 gfx::Rect cleared_rect;
10346 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10347 gfx::Rect(xoffset, yoffset, width, height),
10348 &cleared_rect)) {
10349 DCHECK_GE(cleared_rect.size().GetArea(),
10350 texture->GetLevelClearedRect(target, level).size().GetArea());
10351 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10352 cleared_rect);
10353 } else {
10354 // Otherwise clear part of texture level that is not already cleared.
10355 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10356 level)) {
10357 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10358 "dimensions too big");
10359 return;
10362 } else {
10363 // Write all pixels in below.
10364 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10367 if (copyX != x ||
10368 copyY != y ||
10369 copyWidth != width ||
10370 copyHeight != height) {
10371 // some part was clipped so clear the sub rect.
10372 uint32 pixels_size = 0;
10373 if (!GLES2Util::ComputeImageDataSizes(
10374 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10375 NULL, NULL)) {
10376 LOCAL_SET_GL_ERROR(
10377 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10378 return;
10380 scoped_ptr<char[]> zero(new char[pixels_size]);
10381 memset(zero.get(), 0, pixels_size);
10382 ScopedModifyPixels modify(texture_ref);
10383 glTexSubImage2D(
10384 target, level, xoffset, yoffset, width, height,
10385 format, type, zero.get());
10388 if (copyHeight > 0 && copyWidth > 0) {
10389 GLint dx = copyX - x;
10390 GLint dy = copyY - y;
10391 GLint destX = xoffset + dx;
10392 GLint destY = yoffset + dy;
10393 ScopedModifyPixels modify(texture_ref);
10394 glCopyTexSubImage2D(target, level,
10395 destX, destY, copyX, copyY,
10396 copyWidth, copyHeight);
10399 // This may be a slow command. Exit command processing to allow for
10400 // context preemption and GPU watchdog checks.
10401 ExitCommandProcessingEarly();
10404 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10405 error::Error* error,
10406 const char* function_name,
10407 GLenum target,
10408 GLint level,
10409 GLint xoffset,
10410 GLint yoffset,
10411 GLsizei width,
10412 GLsizei height,
10413 GLenum format,
10414 GLenum type,
10415 const void * data) {
10416 (*error) = error::kNoError;
10417 if (!validators_->texture_target.IsValid(target)) {
10418 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10419 return false;
10421 if (width < 0) {
10422 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10423 return false;
10425 if (height < 0) {
10426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10427 return false;
10429 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10430 &state_, target);
10431 if (!texture_ref) {
10432 LOCAL_SET_GL_ERROR(
10433 GL_INVALID_OPERATION,
10434 function_name, "unknown texture for target");
10435 return false;
10437 Texture* texture = texture_ref->texture();
10438 GLenum current_type = 0;
10439 GLenum internal_format = 0;
10440 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10441 LOCAL_SET_GL_ERROR(
10442 GL_INVALID_OPERATION, function_name, "level does not exist.");
10443 return false;
10445 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10446 function_name, format, type, internal_format, level)) {
10447 return false;
10449 if (type != current_type) {
10450 LOCAL_SET_GL_ERROR(
10451 GL_INVALID_OPERATION,
10452 function_name, "type does not match type of texture.");
10453 return false;
10455 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10456 LOCAL_SET_GL_ERROR(
10457 GL_INVALID_OPERATION,
10458 function_name, "async upload pending for texture");
10459 return false;
10461 if (!texture->ValidForTexture(
10462 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10463 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10464 return false;
10466 if ((GLES2Util::GetChannelsForFormat(format) &
10467 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
10468 && !feature_info_->IsES3Enabled()) {
10469 LOCAL_SET_GL_ERROR(
10470 GL_INVALID_OPERATION,
10471 function_name, "can not supply data for depth or stencil textures");
10472 return false;
10474 if (data == NULL) {
10475 (*error) = error::kOutOfBounds;
10476 return false;
10478 return true;
10481 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10482 GLenum target,
10483 GLint level,
10484 GLint xoffset,
10485 GLint yoffset,
10486 GLsizei width,
10487 GLsizei height,
10488 GLenum format,
10489 GLenum type,
10490 const void * data) {
10491 error::Error error = error::kNoError;
10492 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10493 xoffset, yoffset, width, height, format, type, data)) {
10494 return error;
10496 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10497 &state_, target);
10498 Texture* texture = texture_ref->texture();
10499 GLsizei tex_width = 0;
10500 GLsizei tex_height = 0;
10501 bool ok = texture->GetLevelSize(
10502 target, level, &tex_width, &tex_height, nullptr);
10503 DCHECK(ok);
10504 if (xoffset != 0 || yoffset != 0 ||
10505 width != tex_width || height != tex_height) {
10506 gfx::Rect cleared_rect;
10507 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10508 gfx::Rect(xoffset, yoffset, width, height),
10509 &cleared_rect)) {
10510 DCHECK_GE(cleared_rect.size().GetArea(),
10511 texture->GetLevelClearedRect(target, level).size().GetArea());
10512 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10513 cleared_rect);
10514 } else {
10515 // Otherwise clear part of texture level that is not already cleared.
10516 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10517 level)) {
10518 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
10519 "dimensions too big");
10520 return error::kNoError;
10523 ScopedTextureUploadTimer timer(&texture_state_);
10524 glTexSubImage2D(
10525 target, level, xoffset, yoffset, width, height, format, type, data);
10526 return error::kNoError;
10529 if (!texture_state_.texsubimage_faster_than_teximage &&
10530 !texture->IsImmutable() &&
10531 !texture->HasImages()) {
10532 ScopedTextureUploadTimer timer(&texture_state_);
10533 GLenum internal_format;
10534 GLenum tex_type;
10535 texture->GetLevelType(target, level, &tex_type, &internal_format);
10536 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10537 // to look it up.
10538 glTexImage2D(
10539 target, level, internal_format, width, height, 0, format, type, data);
10540 } else {
10541 ScopedTextureUploadTimer timer(&texture_state_);
10542 glTexSubImage2D(
10543 target, level, xoffset, yoffset, width, height, format, type, data);
10545 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10547 // This may be a slow command. Exit command processing to allow for
10548 // context preemption and GPU watchdog checks.
10549 ExitCommandProcessingEarly();
10550 return error::kNoError;
10553 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10554 const void* cmd_data) {
10555 const gles2::cmds::TexSubImage2D& c =
10556 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10557 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10558 "width", c.width, "height", c.height);
10559 GLboolean internal = static_cast<GLboolean>(c.internal);
10560 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10561 return error::kNoError;
10563 GLenum target = static_cast<GLenum>(c.target);
10564 GLint level = static_cast<GLint>(c.level);
10565 GLint xoffset = static_cast<GLint>(c.xoffset);
10566 GLint yoffset = static_cast<GLint>(c.yoffset);
10567 GLsizei width = static_cast<GLsizei>(c.width);
10568 GLsizei height = static_cast<GLsizei>(c.height);
10569 GLenum format = static_cast<GLenum>(c.format);
10570 GLenum type = static_cast<GLenum>(c.type);
10571 uint32 data_size;
10572 if (!GLES2Util::ComputeImageDataSizes(
10573 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10574 NULL, NULL)) {
10575 return error::kOutOfBounds;
10577 const void* pixels = GetSharedMemoryAs<const void*>(
10578 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10579 return DoTexSubImage2D(
10580 target, level, xoffset, yoffset, width, height, format, type, pixels);
10583 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10584 GLenum target,
10585 GLint level,
10586 GLint xoffset,
10587 GLint yoffset,
10588 GLint zoffset,
10589 GLsizei width,
10590 GLsizei height,
10591 GLsizei depth,
10592 GLenum format,
10593 GLenum type,
10594 const void * data) {
10595 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10596 &state_, target);
10597 if (!texture_ref) {
10598 LOCAL_SET_GL_ERROR(
10599 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10602 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10603 ScopedTextureUploadTimer timer(&texture_state_);
10604 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10605 depth, format, type, data);
10606 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10607 if (error == GL_NO_ERROR) {
10608 // TODO(zmo): This is not 100% correct because only part of the level
10609 // image is cleared.
10610 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10613 // This may be a slow command. Exit command processing to allow for
10614 // context preemption and GPU watchdog checks.
10615 ExitCommandProcessingEarly();
10616 return error::kNoError;
10619 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10620 const void* cmd_data) {
10621 if (!unsafe_es3_apis_enabled())
10622 return error::kUnknownCommand;
10624 const gles2::cmds::TexSubImage3D& c =
10625 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10626 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10627 "widthXheight", c.width * c.height, "depth", c.depth);
10628 GLboolean internal = static_cast<GLboolean>(c.internal);
10629 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10630 return error::kNoError;
10632 GLenum target = static_cast<GLenum>(c.target);
10633 GLint level = static_cast<GLint>(c.level);
10634 GLint xoffset = static_cast<GLint>(c.xoffset);
10635 GLint yoffset = static_cast<GLint>(c.yoffset);
10636 GLint zoffset = static_cast<GLint>(c.zoffset);
10637 GLsizei width = static_cast<GLsizei>(c.width);
10638 GLsizei height = static_cast<GLsizei>(c.height);
10639 GLsizei depth = static_cast<GLsizei>(c.depth);
10640 GLenum format = static_cast<GLenum>(c.format);
10641 GLenum type = static_cast<GLenum>(c.type);
10642 uint32 data_size;
10643 if (!GLES2Util::ComputeImageDataSizes(
10644 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10645 NULL, NULL)) {
10646 return error::kOutOfBounds;
10648 const void* pixels = GetSharedMemoryAs<const void*>(
10649 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10650 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10651 height, depth, format, type, pixels);
10654 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10655 uint32 immediate_data_size,
10656 const void* cmd_data) {
10657 const gles2::cmds::GetVertexAttribPointerv& c =
10658 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10659 GLuint index = static_cast<GLuint>(c.index);
10660 GLenum pname = static_cast<GLenum>(c.pname);
10661 typedef cmds::GetVertexAttribPointerv::Result Result;
10662 Result* result = GetSharedMemoryAs<Result*>(
10663 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10664 if (!result) {
10665 return error::kOutOfBounds;
10667 // Check that the client initialized the result.
10668 if (result->size != 0) {
10669 return error::kInvalidArguments;
10671 if (!validators_->vertex_pointer.IsValid(pname)) {
10672 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10673 "glGetVertexAttribPointerv", pname, "pname");
10674 return error::kNoError;
10676 if (index >= group_->max_vertex_attribs()) {
10677 LOCAL_SET_GL_ERROR(
10678 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10679 return error::kNoError;
10681 result->SetNumResults(1);
10682 *result->GetData() =
10683 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10684 return error::kNoError;
10687 template <class T>
10688 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10689 GLint fake_location,
10690 uint32 shm_id,
10691 uint32 shm_offset,
10692 error::Error* error,
10693 GLint* real_location,
10694 GLuint* service_id,
10695 SizedResult<T>** result_pointer,
10696 GLenum* result_type,
10697 GLsizei* result_size) {
10698 DCHECK(error);
10699 DCHECK(service_id);
10700 DCHECK(result_pointer);
10701 DCHECK(result_type);
10702 DCHECK(result_size);
10703 DCHECK(real_location);
10704 *error = error::kNoError;
10705 // Make sure we have enough room for the result on failure.
10706 SizedResult<T>* result;
10707 result = GetSharedMemoryAs<SizedResult<T>*>(
10708 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10709 if (!result) {
10710 *error = error::kOutOfBounds;
10711 return false;
10713 *result_pointer = result;
10714 // Set the result size to 0 so the client does not have to check for success.
10715 result->SetNumResults(0);
10716 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10717 if (!program) {
10718 return false;
10720 if (!program->IsValid()) {
10721 // Program was not linked successfully. (ie, glLinkProgram)
10722 LOCAL_SET_GL_ERROR(
10723 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10724 return false;
10726 *service_id = program->service_id();
10727 GLint array_index = -1;
10728 const Program::UniformInfo* uniform_info =
10729 program->GetUniformInfoByFakeLocation(
10730 fake_location, real_location, &array_index);
10731 if (!uniform_info) {
10732 // No such location.
10733 LOCAL_SET_GL_ERROR(
10734 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10735 return false;
10737 GLenum type = uniform_info->type;
10738 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10739 if (num_elements == 0) {
10740 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10741 return false;
10743 result = GetSharedMemoryAs<SizedResult<T>*>(
10744 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10745 if (!result) {
10746 *error = error::kOutOfBounds;
10747 return false;
10749 result->SetNumResults(num_elements);
10750 *result_size = num_elements * sizeof(T);
10751 *result_type = type;
10752 return true;
10755 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10756 const void* cmd_data) {
10757 const gles2::cmds::GetUniformiv& c =
10758 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10759 GLuint program = c.program;
10760 GLint fake_location = c.location;
10761 GLuint service_id;
10762 GLenum result_type;
10763 GLsizei result_size;
10764 GLint real_location = -1;
10765 Error error;
10766 cmds::GetUniformiv::Result* result;
10767 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10768 c.params_shm_offset, &error, &real_location,
10769 &service_id, &result, &result_type,
10770 &result_size)) {
10771 glGetUniformiv(
10772 service_id, real_location, result->GetData());
10774 return error;
10777 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10778 const void* cmd_data) {
10779 if (!unsafe_es3_apis_enabled())
10780 return error::kUnknownCommand;
10782 const gles2::cmds::GetUniformuiv& c =
10783 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10784 GLuint program = c.program;
10785 GLint fake_location = c.location;
10786 GLuint service_id;
10787 GLenum result_type;
10788 GLsizei result_size;
10789 GLint real_location = -1;
10790 Error error;
10791 cmds::GetUniformuiv::Result* result;
10792 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10793 c.params_shm_offset, &error, &real_location,
10794 &service_id, &result, &result_type,
10795 &result_size)) {
10796 glGetUniformuiv(
10797 service_id, real_location, result->GetData());
10799 return error;
10802 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10803 const void* cmd_data) {
10804 const gles2::cmds::GetUniformfv& c =
10805 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10806 GLuint program = c.program;
10807 GLint fake_location = c.location;
10808 GLuint service_id;
10809 GLint real_location = -1;
10810 Error error;
10811 cmds::GetUniformfv::Result* result;
10812 GLenum result_type;
10813 GLsizei result_size;
10814 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10815 c.params_shm_offset, &error, &real_location,
10816 &service_id, &result, &result_type,
10817 &result_size)) {
10818 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10819 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10820 GLsizei num_values = result_size / sizeof(GLfloat);
10821 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10822 glGetUniformiv(service_id, real_location, temp.get());
10823 GLfloat* dst = result->GetData();
10824 for (GLsizei ii = 0; ii < num_values; ++ii) {
10825 dst[ii] = (temp[ii] != 0);
10827 } else {
10828 glGetUniformfv(service_id, real_location, result->GetData());
10831 return error;
10834 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10835 uint32 immediate_data_size,
10836 const void* cmd_data) {
10837 const gles2::cmds::GetShaderPrecisionFormat& c =
10838 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10839 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10840 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10841 typedef cmds::GetShaderPrecisionFormat::Result Result;
10842 Result* result = GetSharedMemoryAs<Result*>(
10843 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10844 if (!result) {
10845 return error::kOutOfBounds;
10847 // Check that the client initialized the result.
10848 if (result->success != 0) {
10849 return error::kInvalidArguments;
10851 if (!validators_->shader_type.IsValid(shader_type)) {
10852 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10853 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10854 return error::kNoError;
10856 if (!validators_->shader_precision.IsValid(precision_type)) {
10857 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10858 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10859 return error::kNoError;
10862 result->success = 1; // true
10864 GLint range[2] = { 0, 0 };
10865 GLint precision = 0;
10866 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10868 result->min_range = range[0];
10869 result->max_range = range[1];
10870 result->precision = precision;
10872 return error::kNoError;
10875 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10876 uint32 immediate_data_size,
10877 const void* cmd_data) {
10878 const gles2::cmds::GetAttachedShaders& c =
10879 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10880 uint32 result_size = c.result_size;
10881 GLuint program_id = static_cast<GLuint>(c.program);
10882 Program* program = GetProgramInfoNotShader(
10883 program_id, "glGetAttachedShaders");
10884 if (!program) {
10885 return error::kNoError;
10887 typedef cmds::GetAttachedShaders::Result Result;
10888 uint32 max_count = Result::ComputeMaxResults(result_size);
10889 Result* result = GetSharedMemoryAs<Result*>(
10890 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10891 if (!result) {
10892 return error::kOutOfBounds;
10894 // Check that the client initialized the result.
10895 if (result->size != 0) {
10896 return error::kInvalidArguments;
10898 GLsizei count = 0;
10899 glGetAttachedShaders(
10900 program->service_id(), max_count, &count, result->GetData());
10901 for (GLsizei ii = 0; ii < count; ++ii) {
10902 if (!shader_manager()->GetClientId(result->GetData()[ii],
10903 &result->GetData()[ii])) {
10904 NOTREACHED();
10905 return error::kGenericError;
10908 result->SetNumResults(count);
10909 return error::kNoError;
10912 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10913 uint32 immediate_data_size,
10914 const void* cmd_data) {
10915 const gles2::cmds::GetActiveUniform& c =
10916 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10917 GLuint program_id = c.program;
10918 GLuint index = c.index;
10919 uint32 name_bucket_id = c.name_bucket_id;
10920 typedef cmds::GetActiveUniform::Result Result;
10921 Result* result = GetSharedMemoryAs<Result*>(
10922 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10923 if (!result) {
10924 return error::kOutOfBounds;
10926 // Check that the client initialized the result.
10927 if (result->success != 0) {
10928 return error::kInvalidArguments;
10930 Program* program = GetProgramInfoNotShader(
10931 program_id, "glGetActiveUniform");
10932 if (!program) {
10933 return error::kNoError;
10935 const Program::UniformInfo* uniform_info =
10936 program->GetUniformInfo(index);
10937 if (!uniform_info) {
10938 LOCAL_SET_GL_ERROR(
10939 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10940 return error::kNoError;
10942 result->success = 1; // true.
10943 result->size = uniform_info->size;
10944 result->type = uniform_info->type;
10945 Bucket* bucket = CreateBucket(name_bucket_id);
10946 bucket->SetFromString(uniform_info->name.c_str());
10947 return error::kNoError;
10950 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10951 uint32 immediate_data_size, const void* cmd_data) {
10952 if (!unsafe_es3_apis_enabled())
10953 return error::kUnknownCommand;
10954 const gles2::cmds::GetActiveUniformBlockiv& c =
10955 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10956 GLuint program_id = c.program;
10957 GLuint index = static_cast<GLuint>(c.index);
10958 GLenum pname = static_cast<GLenum>(c.pname);
10959 Program* program = GetProgramInfoNotShader(
10960 program_id, "glGetActiveUniformBlockiv");
10961 if (!program) {
10962 return error::kNoError;
10964 GLuint service_id = program->service_id();
10965 GLint link_status = GL_FALSE;
10966 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10967 if (link_status != GL_TRUE) {
10968 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10969 "glGetActiveActiveUniformBlockiv", "program not linked");
10970 return error::kNoError;
10972 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10973 GLsizei num_values = 1;
10974 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10975 GLint num = 0;
10976 glGetActiveUniformBlockiv(
10977 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10978 GLenum error = glGetError();
10979 if (error != GL_NO_ERROR) {
10980 // Assume this will the same error if calling with pname.
10981 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10982 return error::kNoError;
10984 num_values = static_cast<GLsizei>(num);
10986 typedef cmds::GetActiveUniformBlockiv::Result Result;
10987 Result* result = GetSharedMemoryAs<Result*>(
10988 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10989 GLint* params = result ? result->GetData() : NULL;
10990 if (params == NULL) {
10991 return error::kOutOfBounds;
10993 // Check that the client initialized the result.
10994 if (result->size != 0) {
10995 return error::kInvalidArguments;
10997 glGetActiveUniformBlockiv(service_id, index, pname, params);
10998 GLenum error = glGetError();
10999 if (error == GL_NO_ERROR) {
11000 result->SetNumResults(num_values);
11001 } else {
11002 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11004 return error::kNoError;
11007 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11008 uint32 immediate_data_size, const void* cmd_data) {
11009 if (!unsafe_es3_apis_enabled())
11010 return error::kUnknownCommand;
11011 const gles2::cmds::GetActiveUniformBlockName& c =
11012 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
11013 GLuint program_id = c.program;
11014 GLuint index = c.index;
11015 uint32 name_bucket_id = c.name_bucket_id;
11016 typedef cmds::GetActiveUniformBlockName::Result Result;
11017 Result* result = GetSharedMemoryAs<Result*>(
11018 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11019 if (!result) {
11020 return error::kOutOfBounds;
11022 // Check that the client initialized the result.
11023 if (*result != 0) {
11024 return error::kInvalidArguments;
11026 Program* program = GetProgramInfoNotShader(
11027 program_id, "glGetActiveUniformBlockName");
11028 if (!program) {
11029 return error::kNoError;
11031 GLuint service_id = program->service_id();
11032 GLint link_status = GL_FALSE;
11033 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11034 if (link_status != GL_TRUE) {
11035 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11036 "glGetActiveActiveUniformBlockName", "program not linked");
11037 return error::kNoError;
11039 GLint max_length = 0;
11040 glGetProgramiv(
11041 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
11042 // Increase one so &buffer[0] is always valid.
11043 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
11044 std::vector<char> buffer(buf_size);
11045 GLsizei length = 0;
11046 glGetActiveUniformBlockName(
11047 service_id, index, buf_size, &length, &buffer[0]);
11048 if (length == 0) {
11049 *result = 0;
11050 return error::kNoError;
11052 *result = 1;
11053 Bucket* bucket = CreateBucket(name_bucket_id);
11054 DCHECK_GT(buf_size, length);
11055 DCHECK_EQ(0, buffer[length]);
11056 bucket->SetFromString(&buffer[0]);
11057 return error::kNoError;
11060 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
11061 uint32 immediate_data_size, const void* cmd_data) {
11062 if (!unsafe_es3_apis_enabled())
11063 return error::kUnknownCommand;
11064 const gles2::cmds::GetActiveUniformsiv& c =
11065 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
11066 GLuint program_id = c.program;
11067 GLenum pname = static_cast<GLenum>(c.pname);
11068 Bucket* bucket = GetBucket(c.indices_bucket_id);
11069 if (!bucket) {
11070 return error::kInvalidArguments;
11072 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11073 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11074 typedef cmds::GetActiveUniformsiv::Result Result;
11075 Result* result = GetSharedMemoryAs<Result*>(
11076 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11077 GLint* params = result ? result->GetData() : NULL;
11078 if (params == NULL) {
11079 return error::kOutOfBounds;
11081 // Check that the client initialized the result.
11082 if (result->size != 0) {
11083 return error::kInvalidArguments;
11085 Program* program = GetProgramInfoNotShader(
11086 program_id, "glGetActiveUniformsiv");
11087 if (!program) {
11088 return error::kNoError;
11090 GLuint service_id = program->service_id();
11091 GLint link_status = GL_FALSE;
11092 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11093 if (link_status != GL_TRUE) {
11094 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11095 "glGetActiveUniformsiv", "program not linked");
11096 return error::kNoError;
11098 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11099 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11100 GLenum error = glGetError();
11101 if (error == GL_NO_ERROR) {
11102 result->SetNumResults(count);
11103 } else {
11104 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11106 return error::kNoError;
11109 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11110 const void* cmd_data) {
11111 const gles2::cmds::GetActiveAttrib& c =
11112 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11113 GLuint program_id = c.program;
11114 GLuint index = c.index;
11115 uint32 name_bucket_id = c.name_bucket_id;
11116 typedef cmds::GetActiveAttrib::Result Result;
11117 Result* result = GetSharedMemoryAs<Result*>(
11118 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11119 if (!result) {
11120 return error::kOutOfBounds;
11122 // Check that the client initialized the result.
11123 if (result->success != 0) {
11124 return error::kInvalidArguments;
11126 Program* program = GetProgramInfoNotShader(
11127 program_id, "glGetActiveAttrib");
11128 if (!program) {
11129 return error::kNoError;
11131 const Program::VertexAttrib* attrib_info =
11132 program->GetAttribInfo(index);
11133 if (!attrib_info) {
11134 LOCAL_SET_GL_ERROR(
11135 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11136 return error::kNoError;
11138 result->success = 1; // true.
11139 result->size = attrib_info->size;
11140 result->type = attrib_info->type;
11141 Bucket* bucket = CreateBucket(name_bucket_id);
11142 bucket->SetFromString(attrib_info->name.c_str());
11143 return error::kNoError;
11146 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11147 const void* cmd_data) {
11148 #if 1 // No binary shader support.
11149 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11150 return error::kNoError;
11151 #else
11152 GLsizei n = static_cast<GLsizei>(c.n);
11153 if (n < 0) {
11154 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11155 return error::kNoError;
11157 GLsizei length = static_cast<GLsizei>(c.length);
11158 if (length < 0) {
11159 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11160 return error::kNoError;
11162 uint32 data_size;
11163 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11164 return error::kOutOfBounds;
11166 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11167 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11168 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11169 const void* binary = GetSharedMemoryAs<const void*>(
11170 c.binary_shm_id, c.binary_shm_offset, length);
11171 if (shaders == NULL || binary == NULL) {
11172 return error::kOutOfBounds;
11174 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11175 for (GLsizei ii = 0; ii < n; ++ii) {
11176 Shader* shader = GetShader(shaders[ii]);
11177 if (!shader) {
11178 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11179 return error::kNoError;
11181 service_ids[ii] = shader->service_id();
11183 // TODO(gman): call glShaderBinary
11184 return error::kNoError;
11185 #endif
11188 void GLES2DecoderImpl::DoSwapBuffers() {
11189 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11191 int this_frame_number = frame_number_++;
11192 // TRACE_EVENT for gpu tests:
11193 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11194 TRACE_EVENT_SCOPE_THREAD,
11195 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11196 "width", (is_offscreen ? offscreen_size_.width() :
11197 surface_->GetSize().width()));
11198 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11199 "offscreen", is_offscreen,
11200 "frame", this_frame_number);
11202 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11205 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11206 "GLES2Decoder", "SwapBuffer");
11208 bool is_tracing;
11209 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11210 &is_tracing);
11211 if (is_tracing) {
11212 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11213 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11214 is_offscreen ? offscreen_size_ : surface_->GetSize());
11217 // If offscreen then don't actually SwapBuffers to the display. Just copy
11218 // the rendered frame to another frame buffer.
11219 if (is_offscreen) {
11220 TRACE_EVENT2("gpu", "Offscreen",
11221 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11222 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11223 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11224 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11225 // fix this.
11226 if (workarounds().needs_offscreen_buffer_workaround) {
11227 offscreen_saved_frame_buffer_->Create();
11228 glFinish();
11231 // Allocate the offscreen saved color texture.
11232 DCHECK(offscreen_saved_color_format_);
11233 offscreen_saved_color_texture_->AllocateStorage(
11234 offscreen_size_, offscreen_saved_color_format_, false);
11236 offscreen_saved_frame_buffer_->AttachRenderTexture(
11237 offscreen_saved_color_texture_.get());
11238 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11239 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11240 GL_FRAMEBUFFER_COMPLETE) {
11241 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11242 << "because offscreen saved FBO was incomplete.";
11243 MarkContextLost(error::kUnknown);
11244 group_->LoseContexts(error::kUnknown);
11245 return;
11248 // Clear the offscreen color texture.
11249 // TODO(piman): Is this still necessary?
11251 ScopedFrameBufferBinder binder(this,
11252 offscreen_saved_frame_buffer_->id());
11253 glClearColor(0, 0, 0, 0);
11254 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11255 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11256 glClear(GL_COLOR_BUFFER_BIT);
11257 RestoreClearState();
11261 UpdateParentTextureInfo();
11264 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11265 return;
11266 ScopedGLErrorSuppressor suppressor(
11267 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11269 if (IsOffscreenBufferMultisampled()) {
11270 // For multisampled buffers, resolve the frame buffer.
11271 ScopedResolvedFrameBufferBinder binder(this, true, false);
11272 } else {
11273 ScopedFrameBufferBinder binder(this,
11274 offscreen_target_frame_buffer_->id());
11276 if (offscreen_target_buffer_preserved_) {
11277 // Copy the target frame buffer to the saved offscreen texture.
11278 offscreen_saved_color_texture_->Copy(
11279 offscreen_saved_color_texture_->size(),
11280 offscreen_saved_color_format_);
11281 } else {
11282 // Flip the textures in the parent context via the texture manager.
11283 if (!!offscreen_saved_color_texture_info_.get())
11284 offscreen_saved_color_texture_info_->texture()->
11285 SetServiceId(offscreen_target_color_texture_->id());
11287 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11288 offscreen_target_frame_buffer_->AttachRenderTexture(
11289 offscreen_target_color_texture_.get());
11292 // Ensure the side effects of the copy are visible to the parent
11293 // context. There is no need to do this for ANGLE because it uses a
11294 // single D3D device for all contexts.
11295 if (!feature_info_->gl_version_info().is_angle)
11296 glFlush();
11298 } else {
11299 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11300 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11301 if (!CheckResetStatus()) {
11302 MarkContextLost(error::kUnknown);
11303 group_->LoseContexts(error::kUnknown);
11308 // This may be a slow command. Exit command processing to allow for
11309 // context preemption and GPU watchdog checks.
11310 ExitCommandProcessingEarly();
11313 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11314 context_->SetSwapInterval(interval);
11317 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11318 uint32 immediate_data_size,
11319 const void* cmd_data) {
11320 const gles2::cmds::EnableFeatureCHROMIUM& c =
11321 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11322 Bucket* bucket = GetBucket(c.bucket_id);
11323 if (!bucket || bucket->size() == 0) {
11324 return error::kInvalidArguments;
11326 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11327 Result* result = GetSharedMemoryAs<Result*>(
11328 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11329 if (!result) {
11330 return error::kOutOfBounds;
11332 // Check that the client initialized the result.
11333 if (*result != 0) {
11334 return error::kInvalidArguments;
11336 std::string feature_str;
11337 if (!bucket->GetAsString(&feature_str)) {
11338 return error::kInvalidArguments;
11341 // TODO(gman): make this some kind of table to function pointer thingy.
11342 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11343 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11344 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11345 buffer_manager()->set_allow_fixed_attribs(true);
11346 // TODO(gman): decide how to remove the need for this const_cast.
11347 // I could make validators_ non const but that seems bad as this is the only
11348 // place it is needed. I could make some special friend class of validators
11349 // just to allow this to set them. That seems silly. I could refactor this
11350 // code to use the extension mechanism or the initialization attributes to
11351 // turn this feature on. Given that the only real point of this is to make
11352 // the conformance tests pass and given that there is lots of real work that
11353 // needs to be done it seems like refactoring for one to one of those
11354 // methods is a very low priority.
11355 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11356 } else {
11357 return error::kNoError;
11360 *result = 1; // true.
11361 return error::kNoError;
11364 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11365 uint32 immediate_data_size,
11366 const void* cmd_data) {
11367 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11368 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11369 cmd_data);
11370 Bucket* bucket = CreateBucket(c.bucket_id);
11371 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11372 info->Initialize(disallowed_features_);
11373 bucket->SetFromString(info->extensions().c_str());
11374 return error::kNoError;
11377 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11378 uint32 immediate_data_size,
11379 const void* cmd_data) {
11380 const gles2::cmds::RequestExtensionCHROMIUM& c =
11381 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11382 Bucket* bucket = GetBucket(c.bucket_id);
11383 if (!bucket || bucket->size() == 0) {
11384 return error::kInvalidArguments;
11386 std::string feature_str;
11387 if (!bucket->GetAsString(&feature_str)) {
11388 return error::kInvalidArguments;
11391 bool desire_standard_derivatives = false;
11392 bool desire_frag_depth = false;
11393 bool desire_draw_buffers = false;
11394 bool desire_shader_texture_lod = false;
11395 if (IsWebGLContext()) {
11396 desire_standard_derivatives =
11397 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11398 desire_frag_depth =
11399 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11400 desire_draw_buffers =
11401 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11402 desire_shader_texture_lod =
11403 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11406 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11407 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11408 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11409 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11410 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11411 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11412 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11413 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11414 InitializeShaderTranslator();
11417 UpdateCapabilities();
11419 return error::kNoError;
11422 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11423 uint32 immediate_data_size,
11424 const void* cmd_data) {
11425 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11426 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11427 GLuint program_id = static_cast<GLuint>(c.program);
11428 uint32 bucket_id = c.bucket_id;
11429 Bucket* bucket = CreateBucket(bucket_id);
11430 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11431 Program* program = NULL;
11432 program = GetProgram(program_id);
11433 if (!program || !program->IsValid()) {
11434 return error::kNoError;
11436 program->GetProgramInfo(program_manager(), bucket);
11437 return error::kNoError;
11440 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11441 uint32 immediate_data_size, const void* cmd_data) {
11442 if (!unsafe_es3_apis_enabled())
11443 return error::kUnknownCommand;
11444 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11445 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11446 GLuint program_id = static_cast<GLuint>(c.program);
11447 uint32 bucket_id = c.bucket_id;
11448 Bucket* bucket = CreateBucket(bucket_id);
11449 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11450 Program* program = NULL;
11451 program = GetProgram(program_id);
11452 if (!program || !program->IsValid()) {
11453 return error::kNoError;
11455 program->GetUniformBlocks(bucket);
11456 return error::kNoError;
11459 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11460 uint32 immediate_data_size, const void* cmd_data) {
11461 if (!unsafe_es3_apis_enabled())
11462 return error::kUnknownCommand;
11463 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11464 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11465 GLuint program_id = static_cast<GLuint>(c.program);
11466 uint32 bucket_id = c.bucket_id;
11467 Bucket* bucket = CreateBucket(bucket_id);
11468 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11469 Program* program = NULL;
11470 program = GetProgram(program_id);
11471 if (!program || !program->IsValid()) {
11472 return error::kNoError;
11474 program->GetUniformsES3(bucket);
11475 return error::kNoError;
11478 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11479 uint32 immediate_data_size,
11480 const void* cmd_data) {
11481 if (!unsafe_es3_apis_enabled())
11482 return error::kUnknownCommand;
11483 const gles2::cmds::GetTransformFeedbackVarying& c =
11484 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11485 GLuint program_id = c.program;
11486 GLuint index = c.index;
11487 uint32 name_bucket_id = c.name_bucket_id;
11488 typedef cmds::GetTransformFeedbackVarying::Result Result;
11489 Result* result = GetSharedMemoryAs<Result*>(
11490 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11491 if (!result) {
11492 return error::kOutOfBounds;
11494 // Check that the client initialized the result.
11495 if (result->success != 0) {
11496 return error::kInvalidArguments;
11498 Program* program = GetProgramInfoNotShader(
11499 program_id, "glGetTransformFeedbackVarying");
11500 if (!program) {
11501 return error::kNoError;
11503 GLuint service_id = program->service_id();
11504 GLint link_status = GL_FALSE;
11505 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11506 if (link_status != GL_TRUE) {
11507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11508 "glGetTransformFeedbackVarying", "program not linked");
11509 return error::kNoError;
11511 GLint max_length = 0;
11512 glGetProgramiv(
11513 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11514 max_length = std::max(1, max_length);
11515 std::vector<char> buffer(max_length);
11516 GLsizei length = 0;
11517 GLsizei size = 0;
11518 GLenum type = 0;
11519 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11520 glGetTransformFeedbackVarying(
11521 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11522 GLenum error = glGetError();
11523 if (error != GL_NO_ERROR) {
11524 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11525 return error::kNoError;
11527 result->success = 1; // true.
11528 result->size = static_cast<int32_t>(size);
11529 result->type = static_cast<uint32_t>(type);
11530 Bucket* bucket = CreateBucket(name_bucket_id);
11531 DCHECK(length >= 0 && length < max_length);
11532 buffer[length] = '\0'; // Just to be safe.
11533 bucket->SetFromString(&buffer[0]);
11534 return error::kNoError;
11537 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11538 uint32 immediate_data_size, const void* cmd_data) {
11539 if (!unsafe_es3_apis_enabled())
11540 return error::kUnknownCommand;
11541 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11542 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11543 cmd_data);
11544 GLuint program_id = static_cast<GLuint>(c.program);
11545 uint32 bucket_id = c.bucket_id;
11546 Bucket* bucket = CreateBucket(bucket_id);
11547 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11548 Program* program = NULL;
11549 program = GetProgram(program_id);
11550 if (!program || !program->IsValid()) {
11551 return error::kNoError;
11553 program->GetTransformFeedbackVaryings(bucket);
11554 return error::kNoError;
11557 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11558 return context_lost_reason_;
11561 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11562 GLenum reset_status) const {
11563 switch (reset_status) {
11564 case GL_NO_ERROR:
11565 // TODO(kbr): improve the precision of the error code in this case.
11566 // Consider delegating to context for error code if MakeCurrent fails.
11567 return error::kUnknown;
11568 case GL_GUILTY_CONTEXT_RESET_ARB:
11569 return error::kGuilty;
11570 case GL_INNOCENT_CONTEXT_RESET_ARB:
11571 return error::kInnocent;
11572 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11573 return error::kUnknown;
11576 NOTREACHED();
11577 return error::kUnknown;
11580 bool GLES2DecoderImpl::WasContextLost() const {
11581 return context_was_lost_;
11584 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11585 return WasContextLost() && reset_by_robustness_extension_;
11588 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11589 // Only lose the context once.
11590 if (WasContextLost())
11591 return;
11593 // Don't make GL calls in here, the context might not be current.
11594 context_lost_reason_ = reason;
11595 current_decoder_error_ = error::kLostContext;
11596 context_was_lost_ = true;
11599 bool GLES2DecoderImpl::CheckResetStatus() {
11600 DCHECK(!WasContextLost());
11601 DCHECK(context_->IsCurrent(NULL));
11603 if (IsRobustnessSupported()) {
11604 // If the reason for the call was a GL error, we can try to determine the
11605 // reset status more accurately.
11606 GLenum driver_status = glGetGraphicsResetStatusARB();
11607 if (driver_status == GL_NO_ERROR)
11608 return false;
11610 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11611 << " context lost via ARB/EXT_robustness. Reset status = "
11612 << GLES2Util::GetStringEnum(driver_status);
11614 // Don't pretend we know which client was responsible.
11615 if (workarounds().use_virtualized_gl_contexts)
11616 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11618 switch (driver_status) {
11619 case GL_GUILTY_CONTEXT_RESET_ARB:
11620 MarkContextLost(error::kGuilty);
11621 break;
11622 case GL_INNOCENT_CONTEXT_RESET_ARB:
11623 MarkContextLost(error::kInnocent);
11624 break;
11625 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11626 MarkContextLost(error::kUnknown);
11627 break;
11628 default:
11629 NOTREACHED();
11630 return false;
11632 reset_by_robustness_extension_ = true;
11633 return true;
11635 return false;
11638 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11639 uint32 immediate_data_size,
11640 const void* cmd_data) {
11641 return error::kUnknownCommand;
11644 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11645 uint32 immediate_data_size,
11646 const void* cmd_data) {
11647 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11648 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11649 uint32 sync_point = c.sync_point;
11650 if (wait_sync_point_callback_.is_null())
11651 return error::kNoError;
11653 return wait_sync_point_callback_.Run(sync_point) ?
11654 error::kNoError : error::kDeferCommandUntilLater;
11657 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11658 uint32 immediate_data_size,
11659 const void* cmd_data) {
11660 if (surface_->DeferDraws())
11661 return error::kDeferCommandUntilLater;
11662 if (!surface_->SetBackbufferAllocation(false))
11663 return error::kLostContext;
11664 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11665 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11666 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11667 return error::kNoError;
11670 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11671 GLsizei n, const GLuint* client_ids) {
11672 for (GLsizei ii = 0; ii < n; ++ii) {
11673 if (query_manager_->GetQuery(client_ids[ii])) {
11674 return false;
11677 query_manager_->GenQueries(n, client_ids);
11678 return true;
11681 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11682 GLsizei n, const GLuint* client_ids) {
11683 for (GLsizei ii = 0; ii < n; ++ii) {
11684 query_manager_->RemoveQuery(client_ids[ii]);
11688 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11689 if (query_manager_.get() == NULL) {
11690 return false;
11692 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11693 current_decoder_error_ = error::kOutOfBounds;
11695 return query_manager_->HavePendingQueries();
11698 // Note that if there are no pending readpixels right now,
11699 // this function will call the callback immediately.
11700 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11701 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11702 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11703 } else {
11704 callback.Run();
11708 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
11709 // Note: |did_finish| guarantees that the GPU has passed the fence but
11710 // we cannot assume that GLFence::HasCompleted() will return true yet as
11711 // that's not guaranteed by all GLFence implementations.
11712 while (!pending_readpixel_fences_.empty() &&
11713 (did_finish ||
11714 pending_readpixel_fences_.front()->fence->HasCompleted())) {
11715 std::vector<base::Closure> callbacks =
11716 pending_readpixel_fences_.front()->callbacks;
11717 pending_readpixel_fences_.pop();
11718 for (size_t i = 0; i < callbacks.size(); i++) {
11719 callbacks[i].Run();
11724 bool GLES2DecoderImpl::HasMoreIdleWork() {
11725 return !pending_readpixel_fences_.empty() ||
11726 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11729 void GLES2DecoderImpl::PerformIdleWork() {
11730 ProcessPendingReadPixels(false);
11731 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11732 return;
11733 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11734 ProcessFinishedAsyncTransfers();
11737 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11738 const void* cmd_data) {
11739 const gles2::cmds::BeginQueryEXT& c =
11740 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11741 GLenum target = static_cast<GLenum>(c.target);
11742 GLuint client_id = static_cast<GLuint>(c.id);
11743 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11744 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11746 switch (target) {
11747 case GL_COMMANDS_ISSUED_CHROMIUM:
11748 case GL_LATENCY_QUERY_CHROMIUM:
11749 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11750 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11751 case GL_GET_ERROR_QUERY_CHROMIUM:
11752 break;
11753 case GL_COMMANDS_COMPLETED_CHROMIUM:
11754 if (!features().chromium_sync_query) {
11755 LOCAL_SET_GL_ERROR(
11756 GL_INVALID_OPERATION, "glBeginQueryEXT",
11757 "not enabled for commands completed queries");
11758 return error::kNoError;
11760 break;
11761 case GL_SAMPLES_PASSED:
11762 case GL_ANY_SAMPLES_PASSED:
11763 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
11764 if (!features().occlusion_query_boolean) {
11765 LOCAL_SET_GL_ERROR(
11766 GL_INVALID_OPERATION, "glBeginQueryEXT",
11767 "not enabled for occlusion queries");
11768 return error::kNoError;
11770 break;
11771 case GL_TIME_ELAPSED:
11772 if (!query_manager_->GPUTimingAvailable()) {
11773 LOCAL_SET_GL_ERROR(
11774 GL_INVALID_OPERATION, "glBeginQueryEXT",
11775 "not enabled for timing queries");
11776 return error::kNoError;
11778 break;
11779 default:
11780 LOCAL_SET_GL_ERROR(
11781 GL_INVALID_ENUM, "glBeginQueryEXT",
11782 "unknown query target");
11783 return error::kNoError;
11786 if (query_manager_->GetActiveQuery(target)) {
11787 LOCAL_SET_GL_ERROR(
11788 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11789 return error::kNoError;
11792 if (client_id == 0) {
11793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11794 return error::kNoError;
11797 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11798 if (!query) {
11799 if (!query_manager_->IsValidQuery(client_id)) {
11800 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11801 "glBeginQueryEXT",
11802 "id not made by glGenQueriesEXT");
11803 return error::kNoError;
11805 query = query_manager_->CreateQuery(
11806 target, client_id, sync_shm_id, sync_shm_offset);
11809 if (query->target() != target) {
11810 LOCAL_SET_GL_ERROR(
11811 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11812 return error::kNoError;
11813 } else if (query->shm_id() != sync_shm_id ||
11814 query->shm_offset() != sync_shm_offset) {
11815 DLOG(ERROR) << "Shared memory used by query not the same as before";
11816 return error::kInvalidArguments;
11819 if (!query_manager_->BeginQuery(query)) {
11820 return error::kOutOfBounds;
11823 return error::kNoError;
11826 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11827 const void* cmd_data) {
11828 const gles2::cmds::EndQueryEXT& c =
11829 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11830 GLenum target = static_cast<GLenum>(c.target);
11831 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11833 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
11834 if (!query) {
11835 LOCAL_SET_GL_ERROR(
11836 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11837 return error::kNoError;
11840 if (!query_manager_->EndQuery(query, submit_count)) {
11841 return error::kOutOfBounds;
11844 query_manager_->ProcessPendingTransferQueries();
11846 return error::kNoError;
11849 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
11850 const void* cmd_data) {
11851 const gles2::cmds::QueryCounterEXT& c =
11852 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
11853 GLuint client_id = static_cast<GLuint>(c.id);
11854 GLenum target = static_cast<GLenum>(c.target);
11855 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11856 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11857 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11859 switch (target) {
11860 case GL_TIMESTAMP:
11861 if (!query_manager_->GPUTimingAvailable()) {
11862 LOCAL_SET_GL_ERROR(
11863 GL_INVALID_OPERATION, "glQueryCounterEXT",
11864 "not enabled for timing queries");
11865 return error::kNoError;
11867 break;
11868 default:
11869 LOCAL_SET_GL_ERROR(
11870 GL_INVALID_ENUM, "glQueryCounterEXT",
11871 "unknown query target");
11872 return error::kNoError;
11875 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11876 if (!query) {
11877 if (!query_manager_->IsValidQuery(client_id)) {
11878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11879 "glQueryCounterEXT",
11880 "id not made by glGenQueriesEXT");
11881 return error::kNoError;
11883 query = query_manager_->CreateQuery(
11884 target, client_id, sync_shm_id, sync_shm_offset);
11886 if (!query_manager_->QueryCounter(query, submit_count)) {
11887 return error::kOutOfBounds;
11890 return error::kNoError;
11893 error::Error GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11894 uint32 immediate_data_size, const void* cmd_data) {
11895 const gles2::cmds::SetDisjointValueSyncCHROMIUM& c =
11896 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM*>(cmd_data);
11897 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11898 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11900 query_manager_->SetDisjointSync(sync_shm_id, sync_shm_offset);
11901 return error::kNoError;
11904 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11905 GLsizei n, const GLuint* client_ids) {
11906 for (GLsizei ii = 0; ii < n; ++ii) {
11907 if (GetVertexAttribManager(client_ids[ii])) {
11908 return false;
11912 if (!features().native_vertex_array_object) {
11913 // Emulated VAO
11914 for (GLsizei ii = 0; ii < n; ++ii) {
11915 CreateVertexAttribManager(client_ids[ii], 0, true);
11917 } else {
11918 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11920 glGenVertexArraysOES(n, service_ids.get());
11921 for (GLsizei ii = 0; ii < n; ++ii) {
11922 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11926 return true;
11929 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11930 GLsizei n, const GLuint* client_ids) {
11931 for (GLsizei ii = 0; ii < n; ++ii) {
11932 VertexAttribManager* vao =
11933 GetVertexAttribManager(client_ids[ii]);
11934 if (vao && !vao->IsDeleted()) {
11935 if (state_.vertex_attrib_manager.get() == vao) {
11936 DoBindVertexArrayOES(0);
11938 RemoveVertexAttribManager(client_ids[ii]);
11943 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11944 VertexAttribManager* vao = NULL;
11945 if (client_id != 0) {
11946 vao = GetVertexAttribManager(client_id);
11947 if (!vao) {
11948 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11949 // only allows names that have been previously generated. As such, we do
11950 // not generate new names here.
11951 LOCAL_SET_GL_ERROR(
11952 GL_INVALID_OPERATION,
11953 "glBindVertexArrayOES", "bad vertex array id.");
11954 current_decoder_error_ = error::kNoError;
11955 return;
11957 } else {
11958 vao = state_.default_vertex_attrib_manager.get();
11961 // Only set the VAO state if it's changed
11962 if (state_.vertex_attrib_manager.get() != vao) {
11963 state_.vertex_attrib_manager = vao;
11964 if (!features().native_vertex_array_object) {
11965 EmulateVertexArrayState();
11966 } else {
11967 GLuint service_id = vao->service_id();
11968 glBindVertexArrayOES(service_id);
11973 // Used when OES_vertex_array_object isn't natively supported
11974 void GLES2DecoderImpl::EmulateVertexArrayState() {
11975 // Setup the Vertex attribute state
11976 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11977 RestoreStateForAttrib(vv, true);
11980 // Setup the element buffer
11981 Buffer* element_array_buffer =
11982 state_.vertex_attrib_manager->element_array_buffer();
11983 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11984 element_array_buffer ? element_array_buffer->service_id() : 0);
11987 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11988 const VertexAttribManager* vao =
11989 GetVertexAttribManager(client_id);
11990 return vao && vao->IsValid() && !vao->IsDeleted();
11993 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
11994 GLuint service_id = 0;
11995 return path_manager()->GetPath(client_id, &service_id) &&
11996 glIsPathNV(service_id) == GL_TRUE;
11999 #if defined(OS_MACOSX)
12000 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
12001 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
12002 texture_id);
12003 if (it != texture_to_io_surface_map_.end()) {
12004 // Found a previous IOSurface bound to this texture; release it.
12005 IOSurfaceRef surface = it->second;
12006 CFRelease(surface);
12007 texture_to_io_surface_map_.erase(it);
12010 #endif
12012 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12013 GLenum target, GLsizei width, GLsizei height,
12014 GLuint io_surface_id, GLuint plane) {
12015 #if defined(OS_MACOSX)
12016 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
12017 LOCAL_SET_GL_ERROR(
12018 GL_INVALID_OPERATION,
12019 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12020 return;
12023 if (target != GL_TEXTURE_RECTANGLE_ARB) {
12024 // This might be supported in the future, and if we could require
12025 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12026 // could delete a lot of code. For now, perform strict validation so we
12027 // know what's going on.
12028 LOCAL_SET_GL_ERROR(
12029 GL_INVALID_OPERATION,
12030 "glTexImageIOSurface2DCHROMIUM",
12031 "requires TEXTURE_RECTANGLE_ARB target");
12032 return;
12035 // Default target might be conceptually valid, but disallow it to avoid
12036 // accidents.
12037 TextureRef* texture_ref =
12038 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12039 if (!texture_ref) {
12040 LOCAL_SET_GL_ERROR(
12041 GL_INVALID_OPERATION,
12042 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12043 return;
12046 // Look up the new IOSurface. Note that because of asynchrony
12047 // between processes this might fail; during live resizing the
12048 // plugin process might allocate and release an IOSurface before
12049 // this process gets a chance to look it up. Hold on to any old
12050 // IOSurface in this case.
12051 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
12052 if (!surface) {
12053 LOCAL_SET_GL_ERROR(
12054 GL_INVALID_OPERATION,
12055 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12056 return;
12059 // Release any IOSurface previously bound to this texture.
12060 ReleaseIOSurfaceForTexture(texture_ref->service_id());
12062 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12063 texture_to_io_surface_map_.insert(
12064 std::make_pair(texture_ref->service_id(), surface));
12066 CGLContextObj context =
12067 static_cast<CGLContextObj>(context_->GetHandle());
12069 CGLError err = CGLTexImageIOSurface2D(
12070 context,
12071 target,
12072 GL_RGBA,
12073 width,
12074 height,
12075 GL_BGRA,
12076 GL_UNSIGNED_INT_8_8_8_8_REV,
12077 surface,
12078 plane);
12080 if (err != kCGLNoError) {
12081 LOCAL_SET_GL_ERROR(
12082 GL_INVALID_OPERATION,
12083 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12084 return;
12087 texture_manager()->SetLevelInfo(
12088 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12089 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12091 #else
12092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12093 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12094 #endif
12097 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12098 switch (internalformat) {
12099 case GL_R8:
12100 case GL_R8_SNORM:
12101 case GL_R16F:
12102 case GL_R32F:
12103 return GL_RED;
12104 case GL_R8UI:
12105 case GL_R8I:
12106 case GL_R16UI:
12107 case GL_R16I:
12108 case GL_R32UI:
12109 case GL_R32I:
12110 return GL_RED_INTEGER;
12111 case GL_RG8:
12112 case GL_RG8_SNORM:
12113 case GL_RG16F:
12114 case GL_RG32F:
12115 return GL_RG;
12116 case GL_RG8UI:
12117 case GL_RG8I:
12118 case GL_RG16UI:
12119 case GL_RG16I:
12120 case GL_RG32UI:
12121 case GL_RG32I:
12122 return GL_RG_INTEGER;
12123 case GL_ATC_RGB_AMD:
12124 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12125 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12126 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12127 case GL_ETC1_RGB8_OES:
12128 case GL_RGB8:
12129 case GL_R11F_G11F_B10F:
12130 case GL_RGB565:
12131 case GL_RGB8_SNORM:
12132 case GL_RGB9_E5:
12133 case GL_RGB16F:
12134 case GL_RGB32F:
12135 return GL_RGB;
12136 case GL_RGB8UI:
12137 case GL_RGB8I:
12138 case GL_RGB16UI:
12139 case GL_RGB16I:
12140 case GL_RGB32UI:
12141 case GL_RGB32I:
12142 return GL_RGB_INTEGER;
12143 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12144 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12145 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12146 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12147 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12148 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12149 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12150 case GL_RGBA8:
12151 case GL_SRGB8_ALPHA8:
12152 case GL_RGBA8_SNORM:
12153 case GL_RGBA4:
12154 case GL_RGB5_A1:
12155 case GL_RGB10_A2:
12156 case GL_RGBA16F:
12157 case GL_RGBA32F:
12158 return GL_RGBA;
12159 case GL_RGBA8UI:
12160 case GL_RGBA8I:
12161 case GL_RGB10_A2UI:
12162 case GL_RGBA16UI:
12163 case GL_RGBA16I:
12164 case GL_RGBA32UI:
12165 case GL_RGBA32I:
12166 return GL_RGBA_INTEGER;
12167 case GL_DEPTH_COMPONENT16:
12168 case GL_DEPTH_COMPONENT24:
12169 case GL_DEPTH_COMPONENT32F:
12170 return GL_DEPTH_COMPONENT;
12171 case GL_DEPTH24_STENCIL8:
12172 case GL_DEPTH32F_STENCIL8:
12173 return GL_DEPTH_STENCIL;
12174 case GL_LUMINANCE8_ALPHA8_EXT:
12175 return GL_LUMINANCE_ALPHA;
12176 case GL_LUMINANCE8_EXT:
12177 return GL_LUMINANCE;
12178 case GL_ALPHA8_EXT:
12179 return GL_ALPHA;
12180 case GL_ALPHA32F_EXT:
12181 return GL_ALPHA;
12182 case GL_LUMINANCE32F_EXT:
12183 return GL_LUMINANCE;
12184 case GL_LUMINANCE_ALPHA32F_EXT:
12185 return GL_LUMINANCE_ALPHA;
12186 case GL_ALPHA16F_EXT:
12187 return GL_ALPHA;
12188 case GL_LUMINANCE16F_EXT:
12189 return GL_LUMINANCE;
12190 case GL_LUMINANCE_ALPHA16F_EXT:
12191 return GL_LUMINANCE_ALPHA;
12192 case GL_BGRA8_EXT:
12193 return GL_BGRA_EXT;
12194 default:
12195 return GL_NONE;
12199 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12200 const char* function_name,
12201 GLenum target,
12202 TextureRef* source_texture_ref,
12203 TextureRef* dest_texture_ref,
12204 GLenum dest_internal_format) {
12205 if (!source_texture_ref || !dest_texture_ref) {
12206 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12207 return false;
12210 if (GL_TEXTURE_2D != target) {
12211 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12212 "invalid texture target");
12213 return false;
12216 Texture* source_texture = source_texture_ref->texture();
12217 Texture* dest_texture = dest_texture_ref->texture();
12218 if (source_texture == dest_texture) {
12219 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12220 "source and destination textures are the same");
12221 return false;
12224 if (dest_texture->target() != GL_TEXTURE_2D ||
12225 (source_texture->target() != GL_TEXTURE_2D &&
12226 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12227 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12228 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12229 "invalid texture target binding");
12230 return false;
12233 GLenum source_type = 0;
12234 GLenum source_internal_format = 0;
12235 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12236 &source_internal_format);
12238 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12239 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12240 // renderable on some platforms.
12241 bool valid_dest_format = dest_internal_format == GL_RGB ||
12242 dest_internal_format == GL_RGBA ||
12243 dest_internal_format == GL_BGRA_EXT;
12244 bool valid_source_format =
12245 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12246 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12247 source_internal_format == GL_LUMINANCE ||
12248 source_internal_format == GL_LUMINANCE_ALPHA ||
12249 source_internal_format == GL_BGRA_EXT;
12250 if (!valid_source_format || !valid_dest_format) {
12251 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12252 "invalid internal format");
12253 return false;
12255 return true;
12258 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12259 const char* function_name,
12260 GLenum target,
12261 TextureRef* source_texture_ref,
12262 TextureRef* dest_texture_ref) {
12263 if (!source_texture_ref || !dest_texture_ref) {
12264 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12265 return false;
12268 if (GL_TEXTURE_2D != target) {
12269 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12270 "invalid texture target");
12271 return false;
12274 Texture* source_texture = source_texture_ref->texture();
12275 Texture* dest_texture = dest_texture_ref->texture();
12276 if (source_texture == dest_texture) {
12277 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12278 "source and destination textures are the same");
12279 return false;
12282 if (dest_texture->target() != GL_TEXTURE_2D ||
12283 (source_texture->target() != GL_TEXTURE_2D &&
12284 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12285 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12287 "invalid texture target binding");
12288 return false;
12291 GLenum source_type = 0;
12292 GLenum source_internal_format = 0;
12293 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12294 &source_internal_format);
12296 bool valid_format =
12297 source_internal_format == GL_ATC_RGB_AMD ||
12298 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12299 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12300 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12301 source_internal_format == GL_ETC1_RGB8_OES;
12303 if (!valid_format) {
12304 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12305 "invalid internal format");
12306 return false;
12309 return true;
12312 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12313 GLenum target,
12314 GLuint source_id,
12315 GLuint dest_id,
12316 GLenum internal_format,
12317 GLenum dest_type,
12318 GLboolean unpack_flip_y,
12319 GLboolean unpack_premultiply_alpha,
12320 GLboolean unpack_unmultiply_alpha) {
12321 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12323 TextureRef* source_texture_ref = GetTexture(source_id);
12324 TextureRef* dest_texture_ref = GetTexture(dest_id);
12325 Texture* source_texture = source_texture_ref->texture();
12326 Texture* dest_texture = dest_texture_ref->texture();
12327 int source_width = 0;
12328 int source_height = 0;
12329 gfx::GLImage* image =
12330 source_texture->GetLevelImage(source_texture->target(), 0);
12331 if (image) {
12332 gfx::Size size = image->GetSize();
12333 source_width = size.width();
12334 source_height = size.height();
12335 if (source_width <= 0 || source_height <= 0) {
12336 LOCAL_SET_GL_ERROR(
12337 GL_INVALID_VALUE,
12338 "glCopyTextureChromium", "invalid image size");
12339 return;
12341 } else {
12342 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12343 &source_width, &source_height, nullptr)) {
12344 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12345 "glCopyTextureChromium",
12346 "source texture has no level 0");
12347 return;
12350 // Check that this type of texture is allowed.
12351 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12352 source_width, source_height, 1)) {
12353 LOCAL_SET_GL_ERROR(
12354 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12355 return;
12359 GLenum source_type = 0;
12360 GLenum source_internal_format = 0;
12361 source_texture->GetLevelType(
12362 source_texture->target(), 0, &source_type, &source_internal_format);
12364 if (dest_texture->IsImmutable()) {
12365 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12366 "texture is immutable");
12367 return;
12370 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12371 source_texture_ref, dest_texture_ref,
12372 internal_format)) {
12373 return;
12376 // Clear the source texture if necessary.
12377 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12378 source_texture->target(), 0)) {
12379 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12380 "dimensions too big");
12381 return;
12384 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12385 // needed because it takes 10s of milliseconds to initialize.
12386 if (!copy_texture_CHROMIUM_.get()) {
12387 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12388 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12389 copy_texture_CHROMIUM_->Initialize(this);
12390 RestoreCurrentFramebufferBindings();
12391 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12392 return;
12395 GLenum dest_type_previous = dest_type;
12396 GLenum dest_internal_format = internal_format;
12397 int dest_width = 0;
12398 int dest_height = 0;
12399 bool dest_level_defined = dest_texture->GetLevelSize(
12400 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12402 if (dest_level_defined) {
12403 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12404 &dest_internal_format);
12407 // Resize the destination texture to the dimensions of the source texture.
12408 if (!dest_level_defined || dest_width != source_width ||
12409 dest_height != source_height ||
12410 dest_internal_format != internal_format ||
12411 dest_type_previous != dest_type) {
12412 // Ensure that the glTexImage2D succeeds.
12413 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12414 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12415 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12416 0, internal_format, dest_type, NULL);
12417 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12418 if (error != GL_NO_ERROR) {
12419 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12420 return;
12423 texture_manager()->SetLevelInfo(
12424 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12425 source_height, 1, 0, internal_format, dest_type,
12426 gfx::Rect(source_width, source_height));
12427 } else {
12428 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12429 true);
12432 ScopedModifyPixels modify(dest_texture_ref);
12434 // Try using GLImage::CopyTexSubImage when possible.
12435 bool unpack_premultiply_alpha_change =
12436 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12437 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12438 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12439 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12440 gfx::Rect(0, 0, source_width, source_height))) {
12441 return;
12445 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12447 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12448 // before presenting.
12449 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12450 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12451 // instead of using kIdentityMatrix crbug.com/226218.
12452 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12453 this, source_texture->target(), source_texture->service_id(),
12454 dest_texture->service_id(), source_width, source_height,
12455 unpack_flip_y == GL_TRUE,
12456 unpack_premultiply_alpha == GL_TRUE,
12457 unpack_unmultiply_alpha == GL_TRUE,
12458 kIdentityMatrix);
12459 } else {
12460 copy_texture_CHROMIUM_->DoCopyTexture(
12461 this, source_texture->target(), source_texture->service_id(),
12462 source_internal_format, dest_texture->service_id(), internal_format,
12463 source_width, source_height,
12464 unpack_flip_y == GL_TRUE,
12465 unpack_premultiply_alpha == GL_TRUE,
12466 unpack_unmultiply_alpha == GL_TRUE);
12469 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12472 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12473 GLenum target,
12474 GLuint source_id,
12475 GLuint dest_id,
12476 GLint xoffset,
12477 GLint yoffset,
12478 GLint x,
12479 GLint y,
12480 GLsizei width,
12481 GLsizei height,
12482 GLboolean unpack_flip_y,
12483 GLboolean unpack_premultiply_alpha,
12484 GLboolean unpack_unmultiply_alpha) {
12485 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12487 TextureRef* source_texture_ref = GetTexture(source_id);
12488 TextureRef* dest_texture_ref = GetTexture(dest_id);
12489 Texture* source_texture = source_texture_ref->texture();
12490 Texture* dest_texture = dest_texture_ref->texture();
12491 int source_width = 0;
12492 int source_height = 0;
12493 gfx::GLImage* image =
12494 source_texture->GetLevelImage(source_texture->target(), 0);
12495 if (image) {
12496 gfx::Size size = image->GetSize();
12497 source_width = size.width();
12498 source_height = size.height();
12499 if (source_width <= 0 || source_height <= 0) {
12500 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12501 "invalid image size");
12502 return;
12504 } else {
12505 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12506 &source_width, &source_height, nullptr)) {
12507 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12508 "source texture has no level 0");
12509 return;
12512 // Check that this type of texture is allowed.
12513 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12514 source_width, source_height, 1)) {
12515 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12516 "source texture bad dimensions");
12517 return;
12521 GLenum source_type = 0;
12522 GLenum source_internal_format = 0;
12523 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12524 &source_internal_format);
12525 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12526 width, height, 1, source_type)) {
12527 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12528 "source texture bad dimensions.");
12529 return;
12532 GLenum dest_type = 0;
12533 GLenum dest_internal_format = 0;
12534 bool dest_level_defined = dest_texture->GetLevelType(
12535 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12536 if (!dest_level_defined) {
12537 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12538 "destination texture is not defined");
12539 return;
12541 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12542 yoffset, 0, width, height, 1, dest_type)) {
12543 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12544 "destination texture bad dimensions.");
12545 return;
12548 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12549 source_texture_ref, dest_texture_ref,
12550 dest_internal_format)) {
12551 return;
12554 // Clear the source texture if necessary.
12555 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12556 source_texture->target(), 0)) {
12557 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12558 "source texture dimensions too big");
12559 return;
12562 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12563 // needed because it takes 10s of milliseconds to initialize.
12564 if (!copy_texture_CHROMIUM_.get()) {
12565 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12566 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12567 copy_texture_CHROMIUM_->Initialize(this);
12568 RestoreCurrentFramebufferBindings();
12569 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12570 return;
12573 int dest_width = 0;
12574 int dest_height = 0;
12575 bool ok = dest_texture->GetLevelSize(
12576 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12577 DCHECK(ok);
12578 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12579 height != dest_height) {
12580 gfx::Rect cleared_rect;
12581 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12582 gfx::Rect(xoffset, yoffset, width, height),
12583 &cleared_rect)) {
12584 DCHECK_GE(cleared_rect.size().GetArea(),
12585 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12586 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12587 cleared_rect);
12588 } else {
12589 // Otherwise clear part of texture level that is not already cleared.
12590 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12591 0)) {
12592 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12593 "destination texture dimensions too big");
12594 return;
12597 } else {
12598 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12599 true);
12602 ScopedModifyPixels modify(dest_texture_ref);
12604 // Try using GLImage::CopyTexSubImage when possible.
12605 bool unpack_premultiply_alpha_change =
12606 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12607 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12608 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12609 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12610 gfx::Rect(x, y, width, height))) {
12611 return;
12615 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12617 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12618 // crbug.com/226218.
12619 copy_texture_CHROMIUM_->DoCopySubTexture(
12620 this, source_texture->target(), source_texture->service_id(),
12621 source_internal_format, dest_texture->service_id(), dest_internal_format,
12622 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12623 source_width, source_height,
12624 unpack_flip_y == GL_TRUE,
12625 unpack_premultiply_alpha == GL_TRUE,
12626 unpack_unmultiply_alpha == GL_TRUE);
12628 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12631 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
12632 GLuint source_id,
12633 GLuint dest_id) {
12634 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12636 TextureRef* source_texture_ref = GetTexture(source_id);
12637 TextureRef* dest_texture_ref = GetTexture(dest_id);
12638 Texture* source_texture = source_texture_ref->texture();
12639 Texture* dest_texture = dest_texture_ref->texture();
12640 int source_width = 0;
12641 int source_height = 0;
12642 gfx::GLImage* image =
12643 source_texture->GetLevelImage(source_texture->target(), 0);
12644 if (image) {
12645 gfx::Size size = image->GetSize();
12646 source_width = size.width();
12647 source_height = size.height();
12648 if (source_width <= 0 || source_height <= 0) {
12649 LOCAL_SET_GL_ERROR(
12650 GL_INVALID_VALUE,
12651 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12652 return;
12654 } else {
12655 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12656 &source_width, &source_height, nullptr)) {
12657 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12658 "glCompressedCopyTextureCHROMIUM",
12659 "source texture has no level 0");
12660 return;
12663 // Check that this type of texture is allowed.
12664 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12665 source_width, source_height, 1)) {
12666 LOCAL_SET_GL_ERROR(
12667 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
12668 "Bad dimensions");
12669 return;
12673 GLenum source_type = 0;
12674 GLenum source_internal_format = 0;
12675 source_texture->GetLevelType(
12676 source_texture->target(), 0, &source_type, &source_internal_format);
12678 if (dest_texture->IsImmutable()) {
12679 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12680 "glCompressedCopyTextureCHROMIUM",
12681 "texture is immutable");
12682 return;
12685 if (!ValidateCompressedCopyTextureCHROMIUM(
12686 "glCompressedCopyTextureCHROMIUM",
12687 target,
12688 source_texture_ref, dest_texture_ref)) {
12689 return;
12692 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12693 // needed because it takes 10s of milliseconds to initialize.
12694 if (!copy_texture_CHROMIUM_.get()) {
12695 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12696 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12697 copy_texture_CHROMIUM_->Initialize(this);
12698 RestoreCurrentFramebufferBindings();
12699 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12700 return;
12703 // Clear the source texture if necessary.
12704 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12705 source_texture->target(), 0)) {
12706 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
12707 "dimensions too big");
12708 return;
12711 ScopedTextureBinder binder(
12712 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12714 ScopedModifyPixels modify(dest_texture_ref);
12716 // Try using GLImage::CopyTexImage when possible.
12717 if (image) {
12718 GLenum dest_type = 0;
12719 GLenum dest_internal_format = 0;
12720 int dest_width = 0;
12721 int dest_height = 0;
12722 bool dest_level_defined = dest_texture->GetLevelSize(
12723 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12725 if (dest_level_defined) {
12726 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
12727 &dest_internal_format);
12730 // Resize the destination texture to the dimensions of the source texture.
12731 if (!dest_level_defined || dest_width != source_width ||
12732 dest_height != source_height ||
12733 dest_internal_format != source_internal_format) {
12734 GLsizei source_size = 0;
12736 bool did_get_size = GetCompressedTexSizeInBytes(
12737 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
12738 1, source_internal_format, &source_size);
12739 DCHECK(did_get_size);
12741 // Ensure that the glCompressedTexImage2D succeeds.
12742 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12743 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
12744 source_width, source_height, 0, source_size,
12745 NULL);
12746 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12747 if (error != GL_NO_ERROR) {
12748 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12749 return;
12752 texture_manager()->SetLevelInfo(
12753 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
12754 source_width, source_height, 1, 0, source_internal_format,
12755 source_type, gfx::Rect(source_width, source_height));
12756 } else {
12757 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12758 true);
12761 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12762 gfx::Rect(0, 0, source_width, source_height))) {
12763 return;
12767 TRACE_EVENT0(
12768 "gpu",
12769 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12771 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12773 // As a fallback, copy into a non-compressed GL_RGBA texture.
12774 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12775 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
12776 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12777 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12778 if (error != GL_NO_ERROR) {
12779 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12780 return;
12783 texture_manager()->SetLevelInfo(
12784 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
12785 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12786 gfx::Rect(source_width, source_height));
12788 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12789 // before presenting.
12790 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12791 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12792 // instead of using kIdentityMatrix crbug.com/226218.
12793 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12794 this, source_texture->target(), source_texture->service_id(),
12795 dest_texture->service_id(), source_width, source_height,
12796 false, false, false, kIdentityMatrix);
12797 } else {
12798 copy_texture_CHROMIUM_->DoCopyTexture(
12799 this, source_texture->target(), source_texture->service_id(),
12800 source_internal_format, dest_texture->service_id(), GL_RGBA,
12801 source_width, source_height, false, false, false);
12804 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12807 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
12808 switch (internalformat) {
12809 case GL_R8:
12810 return GL_UNSIGNED_BYTE;
12811 case GL_R8_SNORM:
12812 return GL_BYTE;
12813 case GL_R16F:
12814 return GL_HALF_FLOAT;
12815 case GL_R32F:
12816 return GL_FLOAT;
12817 case GL_R8UI:
12818 return GL_UNSIGNED_BYTE;
12819 case GL_R8I:
12820 return GL_BYTE;
12821 case GL_R16UI:
12822 return GL_UNSIGNED_SHORT;
12823 case GL_R16I:
12824 return GL_SHORT;
12825 case GL_R32UI:
12826 return GL_UNSIGNED_INT;
12827 case GL_R32I:
12828 return GL_INT;
12829 case GL_RG8:
12830 return GL_UNSIGNED_BYTE;
12831 case GL_RG8_SNORM:
12832 return GL_BYTE;
12833 case GL_RG16F:
12834 return GL_HALF_FLOAT;
12835 case GL_RG32F:
12836 return GL_FLOAT;
12837 case GL_RG8UI:
12838 return GL_UNSIGNED_BYTE;
12839 case GL_RG8I:
12840 return GL_BYTE;
12841 case GL_RG16UI:
12842 return GL_UNSIGNED_SHORT;
12843 case GL_RG16I:
12844 return GL_SHORT;
12845 case GL_RG32UI:
12846 return GL_UNSIGNED_INT;
12847 case GL_RG32I:
12848 return GL_INT;
12849 case GL_RGB8:
12850 case GL_SRGB8:
12851 return GL_UNSIGNED_BYTE;
12852 case GL_R11F_G11F_B10F:
12853 return GL_UNSIGNED_INT_10F_11F_11F_REV;
12854 case GL_RGB565:
12855 return GL_UNSIGNED_SHORT_5_6_5;
12856 case GL_RGB8_SNORM:
12857 return GL_BYTE;
12858 case GL_RGB9_E5:
12859 return GL_UNSIGNED_INT_5_9_9_9_REV;
12860 case GL_RGB16F:
12861 return GL_HALF_FLOAT;
12862 case GL_RGB32F:
12863 return GL_FLOAT;
12864 case GL_RGB8UI:
12865 return GL_UNSIGNED_BYTE;
12866 case GL_RGB8I:
12867 return GL_BYTE;
12868 case GL_RGB16UI:
12869 return GL_UNSIGNED_SHORT;
12870 case GL_RGB16I:
12871 return GL_SHORT;
12872 case GL_RGB32UI:
12873 return GL_UNSIGNED_INT;
12874 case GL_RGB32I:
12875 return GL_INT;
12876 case GL_RGBA8:
12877 return GL_UNSIGNED_BYTE;
12878 case GL_SRGB8_ALPHA8:
12879 return GL_UNSIGNED_BYTE;
12880 case GL_RGBA8_SNORM:
12881 return GL_BYTE;
12882 case GL_RGBA4:
12883 return GL_UNSIGNED_SHORT_4_4_4_4;
12884 case GL_RGB10_A2:
12885 return GL_UNSIGNED_INT_2_10_10_10_REV;
12886 case GL_RGB5_A1:
12887 return GL_UNSIGNED_SHORT_5_5_5_1;
12888 case GL_RGBA16F:
12889 return GL_HALF_FLOAT;
12890 case GL_RGBA32F:
12891 return GL_FLOAT;
12892 case GL_RGBA8UI:
12893 return GL_UNSIGNED_BYTE;
12894 case GL_RGBA8I:
12895 return GL_BYTE;
12896 case GL_RGB10_A2UI:
12897 return GL_UNSIGNED_INT_2_10_10_10_REV;
12898 case GL_RGBA16UI:
12899 return GL_UNSIGNED_SHORT;
12900 case GL_RGBA16I:
12901 return GL_SHORT;
12902 case GL_RGBA32I:
12903 return GL_INT;
12904 case GL_RGBA32UI:
12905 return GL_UNSIGNED_INT;
12906 case GL_DEPTH_COMPONENT16:
12907 return GL_UNSIGNED_SHORT;
12908 case GL_DEPTH_COMPONENT24:
12909 return GL_UNSIGNED_INT;
12910 case GL_DEPTH_COMPONENT32F:
12911 return GL_FLOAT;
12912 case GL_DEPTH24_STENCIL8:
12913 return GL_UNSIGNED_INT_24_8;
12914 case GL_DEPTH32F_STENCIL8:
12915 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
12916 case GL_LUMINANCE8_ALPHA8_EXT:
12917 return GL_UNSIGNED_BYTE;
12918 case GL_LUMINANCE8_EXT:
12919 return GL_UNSIGNED_BYTE;
12920 case GL_ALPHA8_EXT:
12921 return GL_UNSIGNED_BYTE;
12922 case GL_ALPHA32F_EXT:
12923 return GL_FLOAT;
12924 case GL_LUMINANCE32F_EXT:
12925 return GL_FLOAT;
12926 case GL_LUMINANCE_ALPHA32F_EXT:
12927 return GL_FLOAT;
12928 case GL_ALPHA16F_EXT:
12929 return GL_HALF_FLOAT_OES;
12930 case GL_LUMINANCE16F_EXT:
12931 return GL_HALF_FLOAT_OES;
12932 case GL_LUMINANCE_ALPHA16F_EXT:
12933 return GL_HALF_FLOAT_OES;
12934 case GL_BGRA8_EXT:
12935 return GL_UNSIGNED_BYTE;
12936 default:
12937 return GL_NONE;
12941 void GLES2DecoderImpl::DoTexStorage2DEXT(
12942 GLenum target,
12943 GLint levels,
12944 GLenum internal_format,
12945 GLsizei width,
12946 GLsizei height) {
12947 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12948 "width", width, "height", height);
12949 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
12950 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
12951 LOCAL_SET_GL_ERROR(
12952 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
12953 return;
12955 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12956 &state_, target);
12957 if (!texture_ref) {
12958 LOCAL_SET_GL_ERROR(
12959 GL_INVALID_OPERATION,
12960 "glTexStorage2DEXT", "unknown texture for target");
12961 return;
12963 Texture* texture = texture_ref->texture();
12964 if (texture->IsAttachedToFramebuffer()) {
12965 framebuffer_state_.clear_state_dirty = true;
12967 if (texture->IsImmutable()) {
12968 LOCAL_SET_GL_ERROR(
12969 GL_INVALID_OPERATION,
12970 "glTexStorage2DEXT", "texture is immutable");
12971 return;
12974 GLenum format = ExtractFormatFromStorageFormat(internal_format);
12975 GLenum type = ExtractTypeFromStorageFormat(internal_format);
12978 GLsizei level_width = width;
12979 GLsizei level_height = height;
12980 uint32 estimated_size = 0;
12981 for (int ii = 0; ii < levels; ++ii) {
12982 uint32 level_size = 0;
12983 if (!GLES2Util::ComputeImageDataSizes(
12984 level_width, level_height, 1, format, type, state_.unpack_alignment,
12985 &estimated_size, NULL, NULL) ||
12986 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
12987 LOCAL_SET_GL_ERROR(
12988 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
12989 return;
12991 level_width = std::max(1, level_width >> 1);
12992 level_height = std::max(1, level_height >> 1);
12994 if (!EnsureGPUMemoryAvailable(estimated_size)) {
12995 LOCAL_SET_GL_ERROR(
12996 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
12997 return;
13001 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13002 glTexStorage2DEXT(target, levels, internal_format, width, height);
13003 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13004 if (error == GL_NO_ERROR) {
13005 GLsizei level_width = width;
13006 GLsizei level_height = height;
13008 GLenum cur_format = feature_info_->IsES3Enabled() ?
13009 internal_format : format;
13010 for (int ii = 0; ii < levels; ++ii) {
13011 if (target == GL_TEXTURE_CUBE_MAP) {
13012 for (int jj = 0; jj < 6; ++jj) {
13013 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
13014 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
13015 level_width, level_height, 1, 0,
13016 format, type, gfx::Rect());
13018 } else {
13019 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
13020 level_width, level_height, 1, 0,
13021 format, type, gfx::Rect());
13023 level_width = std::max(1, level_width >> 1);
13024 level_height = std::max(1, level_height >> 1);
13026 texture->SetImmutable(true);
13030 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13031 uint32 immediate_data_size,
13032 const void* cmd_data) {
13033 return error::kUnknownCommand;
13036 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
13037 const GLbyte* data) {
13038 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13039 "context", logger_.GetLogPrefix(),
13040 "mailbox[0]", static_cast<unsigned char>(data[0]));
13042 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13043 &state_, target);
13044 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
13047 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
13048 GLenum target, const GLbyte* data) {
13049 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13050 "context", logger_.GetLogPrefix(),
13051 "mailbox[0]", static_cast<unsigned char>(data[0]));
13053 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
13054 target, data);
13057 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
13058 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
13059 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13060 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
13061 "mailbox that was not generated by "
13062 "GenMailboxCHROMIUM.";
13064 if (!texture_ref) {
13065 LOCAL_SET_GL_ERROR(
13066 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
13067 return;
13070 Texture* produced = texture_manager()->Produce(texture_ref);
13071 if (!produced) {
13072 LOCAL_SET_GL_ERROR(
13073 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
13074 return;
13077 if (produced->target() != target) {
13078 LOCAL_SET_GL_ERROR(
13079 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
13080 return;
13083 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13086 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13087 const GLbyte* data) {
13088 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13089 "context", logger_.GetLogPrefix(),
13090 "mailbox[0]", static_cast<unsigned char>(data[0]));
13091 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13092 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13093 "mailbox that was not generated by "
13094 "GenMailboxCHROMIUM.";
13096 scoped_refptr<TextureRef> texture_ref =
13097 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13098 if (!texture_ref.get()) {
13099 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13100 "glConsumeTextureCHROMIUM",
13101 "unknown texture for target");
13102 return;
13104 GLuint client_id = texture_ref->client_id();
13105 if (!client_id) {
13106 LOCAL_SET_GL_ERROR(
13107 GL_INVALID_OPERATION,
13108 "glConsumeTextureCHROMIUM", "unknown texture for target");
13109 return;
13111 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13112 if (!texture) {
13113 LOCAL_SET_GL_ERROR(
13114 GL_INVALID_OPERATION,
13115 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13116 return;
13118 if (texture->target() != target) {
13119 LOCAL_SET_GL_ERROR(
13120 GL_INVALID_OPERATION,
13121 "glConsumeTextureCHROMIUM", "invalid target");
13122 return;
13125 DeleteTexturesHelper(1, &client_id);
13126 texture_ref = texture_manager()->Consume(client_id, texture);
13127 glBindTexture(target, texture_ref->service_id());
13129 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13130 unit.bind_target = target;
13131 switch (target) {
13132 case GL_TEXTURE_2D:
13133 unit.bound_texture_2d = texture_ref;
13134 break;
13135 case GL_TEXTURE_CUBE_MAP:
13136 unit.bound_texture_cube_map = texture_ref;
13137 break;
13138 case GL_TEXTURE_EXTERNAL_OES:
13139 unit.bound_texture_external_oes = texture_ref;
13140 break;
13141 case GL_TEXTURE_RECTANGLE_ARB:
13142 unit.bound_texture_rectangle_arb = texture_ref;
13143 break;
13144 default:
13145 NOTREACHED(); // Validation should prevent us getting here.
13146 break;
13150 void GLES2DecoderImpl::EnsureTextureForClientId(
13151 GLenum target,
13152 GLuint client_id) {
13153 TextureRef* texture_ref = GetTexture(client_id);
13154 if (!texture_ref) {
13155 GLuint service_id;
13156 glGenTextures(1, &service_id);
13157 DCHECK_NE(0u, service_id);
13158 texture_ref = CreateTexture(client_id, service_id);
13159 texture_manager()->SetTarget(texture_ref, target);
13160 glBindTexture(target, service_id);
13161 RestoreCurrentTextureBindings(&state_, target);
13165 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13166 // provided is associated with a service_id/TextureRef for consistency, even if
13167 // the resulting texture is incomplete.
13168 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13169 uint32_t immediate_data_size,
13170 const void* cmd_data) {
13171 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13172 *static_cast<
13173 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13174 cmd_data);
13175 GLenum target = static_cast<GLenum>(c.target);
13176 uint32_t data_size;
13177 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13178 return error::kOutOfBounds;
13180 if (data_size > immediate_data_size) {
13181 return error::kOutOfBounds;
13183 const GLbyte* mailbox =
13184 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13185 if (!validators_->texture_bind_target.IsValid(target)) {
13186 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13187 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13188 return error::kNoError;
13190 if (mailbox == NULL) {
13191 return error::kOutOfBounds;
13193 uint32_t client_id = c.client_id;
13194 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13195 return error::kNoError;
13198 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13199 const GLbyte* data, GLuint client_id) {
13200 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13201 "context", logger_.GetLogPrefix(),
13202 "mailbox[0]", static_cast<unsigned char>(data[0]));
13203 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13204 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13205 "passed a mailbox that was not "
13206 "generated by GenMailboxCHROMIUM.";
13208 TextureRef* texture_ref = GetTexture(client_id);
13209 if (texture_ref) {
13210 // No need to call EnsureTextureForClientId here, the client_id already has
13211 // an associated texture.
13212 LOCAL_SET_GL_ERROR(
13213 GL_INVALID_OPERATION,
13214 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13215 return;
13217 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13218 if (!texture) {
13219 EnsureTextureForClientId(target, client_id);
13220 LOCAL_SET_GL_ERROR(
13221 GL_INVALID_OPERATION,
13222 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13223 return;
13226 if (texture->target() != target) {
13227 EnsureTextureForClientId(target, client_id);
13228 LOCAL_SET_GL_ERROR(
13229 GL_INVALID_OPERATION,
13230 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13231 return;
13234 texture_ref = texture_manager()->Consume(client_id, texture);
13237 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
13238 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
13239 return valuebuffer && valuebuffer->IsValid();
13242 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
13243 GLuint client_id) {
13244 Valuebuffer* valuebuffer = NULL;
13245 if (client_id != 0) {
13246 valuebuffer = GetValuebuffer(client_id);
13247 if (!valuebuffer) {
13248 if (!group_->bind_generates_resource()) {
13249 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
13250 "id not generated by glBindValuebufferCHROMIUM");
13251 return;
13254 // It's a new id so make a valuebuffer for it.
13255 CreateValuebuffer(client_id);
13256 valuebuffer = GetValuebuffer(client_id);
13258 valuebuffer->MarkAsValid();
13260 state_.bound_valuebuffer = valuebuffer;
13263 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
13264 GLenum subscription) {
13265 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13266 return;
13268 state_.bound_valuebuffer.get()->AddSubscription(subscription);
13271 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
13272 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13273 return;
13275 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
13278 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
13279 GLenum target,
13280 GLenum subscription) {
13281 if (!CheckCurrentValuebufferForSubscription(
13282 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
13283 return;
13285 if (!CheckSubscriptionTarget(location, subscription,
13286 "glPopulateSubscribedValuesCHROMIUM")) {
13287 return;
13289 const ValueState* state =
13290 state_.bound_valuebuffer.get()->GetState(subscription);
13291 if (state) {
13292 switch (subscription) {
13293 case GL_MOUSE_POSITION_CHROMIUM:
13294 DoUniform2iv(location, 1, state->int_value);
13295 break;
13296 default:
13297 NOTREACHED() << "Unhandled uniform subscription target "
13298 << subscription;
13299 break;
13304 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13305 GLsizei length, const GLchar* marker) {
13306 if (!marker) {
13307 marker = "";
13309 debug_marker_manager_.SetMarker(
13310 length ? std::string(marker, length) : std::string(marker));
13313 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13314 GLsizei /*length*/, const GLchar* /*marker*/) {
13317 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13320 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13321 GLenum target, GLint image_id) {
13322 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13324 if (target == GL_TEXTURE_CUBE_MAP) {
13325 LOCAL_SET_GL_ERROR(
13326 GL_INVALID_ENUM,
13327 "glBindTexImage2DCHROMIUM", "invalid target");
13328 return;
13331 // Default target might be conceptually valid, but disallow it to avoid
13332 // accidents.
13333 TextureRef* texture_ref =
13334 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13335 if (!texture_ref) {
13336 LOCAL_SET_GL_ERROR(
13337 GL_INVALID_OPERATION,
13338 "glBindTexImage2DCHROMIUM", "no texture bound");
13339 return;
13342 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13343 if (!gl_image) {
13344 LOCAL_SET_GL_ERROR(
13345 GL_INVALID_OPERATION,
13346 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13347 return;
13351 ScopedGLErrorSuppressor suppressor(
13352 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13353 if (!gl_image->BindTexImage(target)) {
13354 LOCAL_SET_GL_ERROR(
13355 GL_INVALID_OPERATION,
13356 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13357 return;
13361 gfx::Size size = gl_image->GetSize();
13362 texture_manager()->SetLevelInfo(
13363 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
13364 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
13365 gfx::Rect(size));
13366 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
13369 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13370 GLenum target, GLint image_id) {
13371 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13373 // Default target might be conceptually valid, but disallow it to avoid
13374 // accidents.
13375 TextureRef* texture_ref =
13376 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13377 if (!texture_ref) {
13378 LOCAL_SET_GL_ERROR(
13379 GL_INVALID_OPERATION,
13380 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13381 return;
13384 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13385 if (!gl_image) {
13386 LOCAL_SET_GL_ERROR(
13387 GL_INVALID_OPERATION,
13388 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13389 return;
13392 // Do nothing when image is not currently bound.
13393 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
13394 return;
13397 ScopedGLErrorSuppressor suppressor(
13398 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13399 gl_image->ReleaseTexImage(target);
13402 texture_manager()->SetLevelInfo(
13403 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
13404 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
13407 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13408 uint32 immediate_data_size,
13409 const void* cmd_data) {
13410 const gles2::cmds::TraceBeginCHROMIUM& c =
13411 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
13412 Bucket* category_bucket = GetBucket(c.category_bucket_id);
13413 Bucket* name_bucket = GetBucket(c.name_bucket_id);
13414 if (!category_bucket || category_bucket->size() == 0 ||
13415 !name_bucket || name_bucket->size() == 0) {
13416 return error::kInvalidArguments;
13419 std::string category_name;
13420 std::string trace_name;
13421 if (!category_bucket->GetAsString(&category_name) ||
13422 !name_bucket->GetAsString(&trace_name)) {
13423 return error::kInvalidArguments;
13426 debug_marker_manager_.PushGroup(trace_name);
13427 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
13428 LOCAL_SET_GL_ERROR(
13429 GL_INVALID_OPERATION,
13430 "glTraceBeginCHROMIUM", "unable to create begin trace");
13431 return error::kNoError;
13433 return error::kNoError;
13436 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13437 debug_marker_manager_.PopGroup();
13438 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
13439 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13440 "glTraceEndCHROMIUM", "no trace begin found");
13441 return;
13445 void GLES2DecoderImpl::DoDrawBuffersEXT(
13446 GLsizei count, const GLenum* bufs) {
13447 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
13448 LOCAL_SET_GL_ERROR(
13449 GL_INVALID_VALUE,
13450 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13451 return;
13454 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
13455 if (framebuffer) {
13456 for (GLsizei i = 0; i < count; ++i) {
13457 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
13458 bufs[i] != GL_NONE) {
13459 LOCAL_SET_GL_ERROR(
13460 GL_INVALID_OPERATION,
13461 "glDrawBuffersEXT",
13462 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13463 return;
13466 glDrawBuffersARB(count, bufs);
13467 framebuffer->SetDrawBuffers(count, bufs);
13468 } else { // backbuffer
13469 if (count > 1 ||
13470 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
13471 LOCAL_SET_GL_ERROR(
13472 GL_INVALID_OPERATION,
13473 "glDrawBuffersEXT",
13474 "more than one buffer or bufs not GL_NONE or GL_BACK");
13475 return;
13477 GLenum mapped_buf = bufs[0];
13478 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13479 bufs[0] == GL_BACK) {
13480 mapped_buf = GL_COLOR_ATTACHMENT0;
13482 glDrawBuffersARB(count, &mapped_buf);
13483 back_buffer_draw_buffer_ = bufs[0];
13487 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
13488 MarkContextLost(GetContextLostReasonFromResetStatus(current));
13489 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
13490 reset_by_robustness_extension_ = true;
13493 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13494 // On Adreno Android devices we need to use a workaround to force caches to
13495 // clear.
13496 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
13497 context_->ReleaseCurrent(nullptr);
13498 context_->MakeCurrent(surface_.get());
13502 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
13503 const GLfloat* matrix) {
13504 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13505 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13506 if (!features().chromium_path_rendering) {
13507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13508 "glMatrixLoadfCHROMIUM",
13509 "function not available");
13510 return;
13513 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13514 ? state_.projection_matrix
13515 : state_.modelview_matrix;
13516 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
13517 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13518 // since the values of the _NV and _CHROMIUM tokens match.
13519 glMatrixLoadfEXT(matrix_mode, matrix);
13522 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
13523 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13524 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13526 if (!features().chromium_path_rendering) {
13527 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13528 "glMatrixLoadIdentityCHROMIUM",
13529 "function not available");
13530 return;
13533 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13534 ? state_.projection_matrix
13535 : state_.modelview_matrix;
13536 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
13537 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13538 // since the values of the _NV and _CHROMIUM tokens match.
13539 glMatrixLoadIdentityEXT(matrix_mode);
13542 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13543 const char* function_name,
13544 TextureRef* texture_ref,
13545 GLenum target,
13546 GLint level,
13547 const void * data) {
13548 // We only support async uploads to 2D textures for now.
13549 if (GL_TEXTURE_2D != target) {
13550 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
13551 return false;
13553 // We only support uploads to level zero for now.
13554 if (level != 0) {
13555 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
13556 return false;
13558 // A transfer buffer must be bound, even for asyncTexImage2D.
13559 if (data == NULL) {
13560 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
13561 return false;
13563 // We only support one async transfer in progress.
13564 if (!texture_ref ||
13565 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
13566 LOCAL_SET_GL_ERROR(
13567 GL_INVALID_OPERATION,
13568 function_name, "transfer already in progress");
13569 return false;
13571 return true;
13574 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13575 uint32 async_upload_token,
13576 uint32 sync_data_shm_id,
13577 uint32 sync_data_shm_offset) {
13578 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
13579 if (!buffer.get() ||
13580 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
13581 return base::Closure();
13583 AsyncMemoryParams mem_params(buffer,
13584 sync_data_shm_offset,
13585 sizeof(AsyncUploadSync));
13587 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
13588 new AsyncUploadTokenCompletionObserver(async_upload_token));
13590 return base::Bind(
13591 &AsyncPixelTransferManager::AsyncNotifyCompletion,
13592 base::Unretained(GetAsyncPixelTransferManager()),
13593 mem_params,
13594 observer);
13597 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13598 uint32 immediate_data_size,
13599 const void* cmd_data) {
13600 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
13601 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
13602 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13603 GLenum target = static_cast<GLenum>(c.target);
13604 GLint level = static_cast<GLint>(c.level);
13605 GLenum internal_format = static_cast<GLenum>(c.internalformat);
13606 GLsizei width = static_cast<GLsizei>(c.width);
13607 GLsizei height = static_cast<GLsizei>(c.height);
13608 GLint border = static_cast<GLint>(c.border);
13609 GLenum format = static_cast<GLenum>(c.format);
13610 GLenum type = static_cast<GLenum>(c.type);
13611 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
13612 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
13613 uint32 pixels_size;
13614 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13615 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13616 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13618 base::ScopedClosureRunner scoped_completion_callback;
13619 if (async_upload_token) {
13620 base::Closure completion_closure =
13621 AsyncUploadTokenCompletionClosure(async_upload_token,
13622 sync_data_shm_id,
13623 sync_data_shm_offset);
13624 if (completion_closure.is_null())
13625 return error::kInvalidArguments;
13627 scoped_completion_callback.Reset(completion_closure);
13630 // TODO(epenner): Move this and copies of this memory validation
13631 // into ValidateTexImage2D step.
13632 if (!GLES2Util::ComputeImageDataSizes(
13633 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
13634 NULL, NULL)) {
13635 return error::kOutOfBounds;
13637 const void* pixels = NULL;
13638 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
13639 pixels = GetSharedMemoryAs<const void*>(
13640 pixels_shm_id, pixels_shm_offset, pixels_size);
13641 if (!pixels) {
13642 return error::kOutOfBounds;
13646 TextureManager::DoTexImageArguments args = {
13647 target, level, internal_format, width, height, 1, border, format, type,
13648 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
13649 TextureRef* texture_ref;
13650 // All the normal glTexSubImage2D validation.
13651 if (!texture_manager()->ValidateTexImage(
13652 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
13653 return error::kNoError;
13656 // Extra async validation.
13657 Texture* texture = texture_ref->texture();
13658 if (!ValidateAsyncTransfer(
13659 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
13660 return error::kNoError;
13662 // Don't allow async redefinition of a textures.
13663 if (texture->IsDefined()) {
13664 LOCAL_SET_GL_ERROR(
13665 GL_INVALID_OPERATION,
13666 "glAsyncTexImage2DCHROMIUM", "already defined");
13667 return error::kNoError;
13670 if (!EnsureGPUMemoryAvailable(pixels_size)) {
13671 LOCAL_SET_GL_ERROR(
13672 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
13673 return error::kNoError;
13676 // Setup the parameters.
13677 AsyncTexImage2DParams tex_params = {
13678 target, level, static_cast<GLenum>(internal_format),
13679 width, height, border, format, type};
13680 AsyncMemoryParams mem_params(
13681 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
13683 // Set up the async state if needed, and make the texture
13684 // immutable so the async state stays valid. The level info
13685 // is set up lazily when the transfer completes.
13686 AsyncPixelTransferDelegate* delegate =
13687 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
13688 tex_params);
13689 texture->SetImmutable(true);
13691 delegate->AsyncTexImage2D(
13692 tex_params,
13693 mem_params,
13694 base::Bind(&TextureManager::SetLevelInfoFromParams,
13695 // The callback is only invoked if the transfer delegate still
13696 // exists, which implies through manager->texture_ref->state
13697 // ownership that both of these pointers are valid.
13698 base::Unretained(texture_manager()),
13699 base::Unretained(texture_ref),
13700 tex_params));
13701 return error::kNoError;
13704 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13705 uint32 immediate_data_size,
13706 const void* cmd_data) {
13707 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
13708 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
13709 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13710 GLenum target = static_cast<GLenum>(c.target);
13711 GLint level = static_cast<GLint>(c.level);
13712 GLint xoffset = static_cast<GLint>(c.xoffset);
13713 GLint yoffset = static_cast<GLint>(c.yoffset);
13714 GLsizei width = static_cast<GLsizei>(c.width);
13715 GLsizei height = static_cast<GLsizei>(c.height);
13716 GLenum format = static_cast<GLenum>(c.format);
13717 GLenum type = static_cast<GLenum>(c.type);
13718 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13719 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13720 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13722 base::ScopedClosureRunner scoped_completion_callback;
13723 if (async_upload_token) {
13724 base::Closure completion_closure =
13725 AsyncUploadTokenCompletionClosure(async_upload_token,
13726 sync_data_shm_id,
13727 sync_data_shm_offset);
13728 if (completion_closure.is_null())
13729 return error::kInvalidArguments;
13731 scoped_completion_callback.Reset(completion_closure);
13734 // TODO(epenner): Move this and copies of this memory validation
13735 // into ValidateTexSubImage2D step.
13736 uint32 data_size;
13737 if (!GLES2Util::ComputeImageDataSizes(
13738 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13739 NULL, NULL)) {
13740 return error::kOutOfBounds;
13742 const void* pixels = GetSharedMemoryAs<const void*>(
13743 c.data_shm_id, c.data_shm_offset, data_size);
13745 // All the normal glTexSubImage2D validation.
13746 error::Error error = error::kNoError;
13747 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13748 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13749 return error;
13752 // Extra async validation.
13753 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13754 &state_, target);
13755 Texture* texture = texture_ref->texture();
13756 if (!ValidateAsyncTransfer(
13757 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13758 return error::kNoError;
13760 // Guarantee async textures are always 'cleared' as follows:
13761 // - AsyncTexImage2D can not redefine an existing texture
13762 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13763 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13764 // - Textures become immutable after an async call.
13765 // This way we know in all cases that an async texture is always clear.
13766 if (!texture->SafeToRenderFrom()) {
13767 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13768 target, level)) {
13769 LOCAL_SET_GL_ERROR(
13770 GL_OUT_OF_MEMORY,
13771 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13772 return error::kNoError;
13776 // Setup the parameters.
13777 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
13778 width, height, format, type};
13779 AsyncMemoryParams mem_params(
13780 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
13781 AsyncPixelTransferDelegate* delegate =
13782 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13783 if (!delegate) {
13784 // TODO(epenner): We may want to enforce exclusive use
13785 // of async APIs in which case this should become an error,
13786 // (the texture should have been async defined).
13787 AsyncTexImage2DParams define_params = {target, level,
13788 0, 0, 0, 0, 0, 0};
13789 texture->GetLevelSize(
13790 target, level, &define_params.width, &define_params.height, nullptr);
13791 texture->GetLevelType(
13792 target, level, &define_params.type, &define_params.internal_format);
13793 // Set up the async state if needed, and make the texture
13794 // immutable so the async state stays valid.
13795 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
13796 texture_ref, define_params);
13797 texture->SetImmutable(true);
13800 delegate->AsyncTexSubImage2D(tex_params, mem_params);
13801 return error::kNoError;
13804 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13805 uint32 immediate_data_size,
13806 const void* cmd_data) {
13807 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
13808 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
13809 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13810 GLenum target = static_cast<GLenum>(c.target);
13812 if (GL_TEXTURE_2D != target) {
13813 LOCAL_SET_GL_ERROR(
13814 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
13815 return error::kNoError;
13817 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13818 &state_, target);
13819 if (!texture_ref) {
13820 LOCAL_SET_GL_ERROR(
13821 GL_INVALID_OPERATION,
13822 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13823 return error::kNoError;
13825 AsyncPixelTransferDelegate* delegate =
13826 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13827 if (!delegate) {
13828 LOCAL_SET_GL_ERROR(
13829 GL_INVALID_OPERATION,
13830 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13831 return error::kNoError;
13833 delegate->WaitForTransferCompletion();
13834 ProcessFinishedAsyncTransfers();
13835 return error::kNoError;
13838 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13839 uint32 immediate_data_size,
13840 const void* data) {
13841 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13843 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13844 ProcessFinishedAsyncTransfers();
13845 return error::kNoError;
13848 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
13849 uint32_t immediate_data_size, const void* cmd_data) {
13850 if (!unsafe_es3_apis_enabled())
13851 return error::kUnknownCommand;
13852 const gles2::cmds::UniformBlockBinding& c =
13853 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
13854 GLuint client_id = c.program;
13855 GLuint index = static_cast<GLuint>(c.index);
13856 GLuint binding = static_cast<GLuint>(c.binding);
13857 Program* program = GetProgramInfoNotShader(
13858 client_id, "glUniformBlockBinding");
13859 if (!program) {
13860 return error::kNoError;
13862 GLuint service_id = program->service_id();
13863 glUniformBlockBinding(service_id, index, binding);
13864 return error::kNoError;
13867 error::Error GLES2DecoderImpl::HandleClientWaitSync(
13868 uint32_t immediate_data_size, const void* cmd_data) {
13869 if (!unsafe_es3_apis_enabled())
13870 return error::kUnknownCommand;
13871 const gles2::cmds::ClientWaitSync& c =
13872 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
13873 GLuint sync = static_cast<GLuint>(c.sync);
13874 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13875 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13876 typedef cmds::ClientWaitSync::Result Result;
13877 Result* result_dst = GetSharedMemoryAs<Result*>(
13878 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
13879 if (!result_dst) {
13880 return error::kOutOfBounds;
13882 if (*result_dst != GL_WAIT_FAILED) {
13883 return error::kInvalidArguments;
13885 GLsync service_sync = 0;
13886 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13887 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
13888 return error::kNoError;
13890 *result_dst = glClientWaitSync(service_sync, flags, timeout);
13891 return error::kNoError;
13894 error::Error GLES2DecoderImpl::HandleWaitSync(
13895 uint32_t immediate_data_size, const void* cmd_data) {
13896 if (!unsafe_es3_apis_enabled())
13897 return error::kUnknownCommand;
13898 const gles2::cmds::WaitSync& c =
13899 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
13900 GLuint sync = static_cast<GLuint>(c.sync);
13901 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13902 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13903 GLsync service_sync = 0;
13904 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13905 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
13906 return error::kNoError;
13908 glWaitSync(service_sync, flags, timeout);
13909 return error::kNoError;
13912 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
13913 uint32_t immediate_data_size, const void* cmd_data) {
13914 if (!unsafe_es3_apis_enabled())
13915 return error::kUnknownCommand;
13916 const gles2::cmds::GetInternalformativ& c =
13917 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
13918 GLenum target = static_cast<GLenum>(c.target);
13919 GLenum format = static_cast<GLenum>(c.format);
13920 GLenum pname = static_cast<GLenum>(c.pname);
13921 if (!validators_->render_buffer_target.IsValid(target)) {
13922 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
13923 return error::kNoError;
13925 if (!validators_->render_buffer_format.IsValid(format)) {
13926 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
13927 return error::kNoError;
13929 if (!validators_->internal_format_parameter.IsValid(pname)) {
13930 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
13931 return error::kNoError;
13933 typedef cmds::GetInternalformativ::Result Result;
13934 GLsizei num_values = 0;
13935 switch (pname) {
13936 case GL_NUM_SAMPLE_COUNTS:
13937 num_values = 1;
13938 break;
13939 case GL_SAMPLES:
13941 GLint value = 0;
13942 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
13943 num_values = static_cast<GLsizei>(value);
13945 break;
13946 default:
13947 NOTREACHED();
13948 break;
13950 Result* result = GetSharedMemoryAs<Result*>(
13951 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
13952 GLint* params = result ? result->GetData() : NULL;
13953 if (params == NULL) {
13954 return error::kOutOfBounds;
13956 // Check that the client initialized the result.
13957 if (result->size != 0) {
13958 return error::kInvalidArguments;
13960 glGetInternalformativ(target, format, pname, num_values, params);
13961 result->SetNumResults(num_values);
13962 return error::kNoError;
13965 error::Error GLES2DecoderImpl::HandleMapBufferRange(
13966 uint32_t immediate_data_size, const void* cmd_data) {
13967 if (!unsafe_es3_apis_enabled()) {
13968 return error::kUnknownCommand;
13970 const gles2::cmds::MapBufferRange& c =
13971 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
13972 GLenum target = static_cast<GLenum>(c.target);
13973 GLbitfield access = static_cast<GLbitfield>(c.access);
13974 GLintptr offset = static_cast<GLintptr>(c.offset);
13975 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
13977 typedef cmds::MapBufferRange::Result Result;
13978 Result* result = GetSharedMemoryAs<Result*>(
13979 c.result_shm_id, c.result_shm_offset, sizeof(*result));
13980 if (!result) {
13981 return error::kOutOfBounds;
13983 if (*result != 0) {
13984 *result = 0;
13985 return error::kInvalidArguments;
13987 int8_t* mem =
13988 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
13989 if (!mem) {
13990 return error::kOutOfBounds;
13993 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
13994 if ((access & mask) == mask) {
13995 // TODO(zmo): To be on the safe side, always map
13996 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13997 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
13998 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
14000 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14001 // undefined behaviors.
14002 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
14003 if ((access & mask) == mask) {
14004 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
14005 "incompatible access bits");
14006 return error::kNoError;
14008 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
14009 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
14010 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14011 access = (access | GL_MAP_READ_BIT);
14013 void* ptr = glMapBufferRange(target, offset, size, access);
14014 if (ptr == nullptr) {
14015 return error::kNoError;
14017 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14018 DCHECK(buffer);
14019 buffer->SetMappedRange(offset, size, access, ptr,
14020 GetSharedMemoryBuffer(c.data_shm_id));
14021 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14022 memcpy(mem, ptr, size);
14024 *result = 1;
14025 return error::kNoError;
14028 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
14029 uint32_t immediate_data_size, const void* cmd_data) {
14030 if (!unsafe_es3_apis_enabled()) {
14031 return error::kUnknownCommand;
14033 const gles2::cmds::UnmapBuffer& c =
14034 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
14035 GLenum target = static_cast<GLenum>(c.target);
14037 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14038 if (!buffer) {
14039 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
14040 return error::kNoError;
14042 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
14043 if (!mapped_range) {
14044 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
14045 "buffer is unmapped");
14046 return error::kNoError;
14048 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
14049 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
14050 GL_MAP_FLUSH_EXPLICIT_BIT) {
14051 // If we don't need to write back, or explict flush is required, no copying
14052 // back is needed.
14053 } else {
14054 void* mem = mapped_range->GetShmPointer();
14055 if (!mem) {
14056 return error::kOutOfBounds;
14058 DCHECK(mapped_range->pointer);
14059 memcpy(mapped_range->pointer, mem, mapped_range->size);
14061 buffer->RemoveMappedRange();
14062 GLboolean rt = glUnmapBuffer(target);
14063 if (rt == GL_FALSE) {
14064 // At this point, we have already done the necessary validation, so
14065 // GL_FALSE indicates data corruption.
14066 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14067 // the second unmap could still return GL_FALSE. For now, we simply lose
14068 // the contexts in the share group.
14069 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14070 // Need to lose current context before broadcasting!
14071 MarkContextLost(error::kGuilty);
14072 group_->LoseContexts(error::kInnocent);
14073 return error::kLostContext;
14075 return error::kNoError;
14078 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14079 TextureRef* texture_ref) {
14080 Texture* texture = texture_ref->texture();
14081 DoDidUseTexImageIfNeeded(texture, texture->target());
14084 // Note that GL_LOST_CONTEXT is specific to GLES.
14085 // For desktop GL we have to query the reset status proactively.
14086 void GLES2DecoderImpl::OnContextLostError() {
14087 if (!WasContextLost()) {
14088 // Need to lose current context before broadcasting!
14089 CheckResetStatus();
14090 group_->LoseContexts(error::kUnknown);
14091 reset_by_robustness_extension_ = true;
14095 void GLES2DecoderImpl::OnOutOfMemoryError() {
14096 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14097 error::ContextLostReason other = error::kOutOfMemory;
14098 if (CheckResetStatus()) {
14099 other = error::kUnknown;
14100 } else {
14101 // Need to lose current context before broadcasting!
14102 MarkContextLost(error::kOutOfMemory);
14104 group_->LoseContexts(other);
14108 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14109 uint32 immediate_data_size,
14110 const void* cmd_data) {
14111 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14112 const gles2::cmds::GenPathsCHROMIUM& c =
14113 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14114 if (!features().chromium_path_rendering) {
14115 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14116 "function not available");
14117 return error::kNoError;
14120 GLsizei range = static_cast<GLsizei>(c.range);
14121 if (range < 0) {
14122 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14123 return error::kNoError;
14126 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14127 if (first_client_id == 0)
14128 return error::kInvalidArguments;
14130 if (range == 0)
14131 return error::kNoError;
14133 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14134 return error::kInvalidArguments;
14136 return error::kNoError;
14138 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14139 uint32_t immediate_data_size,
14140 const void* cmd_data) {
14141 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14142 const gles2::cmds::DeletePathsCHROMIUM& c =
14143 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14144 if (!features().chromium_path_rendering) {
14145 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14146 "function not available");
14147 return error::kNoError;
14150 GLsizei range = static_cast<GLsizei>(c.range);
14151 if (range < 0) {
14152 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14153 return error::kNoError;
14156 if (range == 0)
14157 return error::kNoError;
14159 GLuint first_client_id = c.first_client_id;
14160 // first_client_id can be 0, because non-existing path ids are skipped.
14162 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14163 return error::kInvalidArguments;
14165 return error::kNoError;
14168 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14169 uint32 immediate_data_size,
14170 const void* cmd_data) {
14171 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14172 const gles2::cmds::PathCommandsCHROMIUM& c =
14173 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14174 if (!features().chromium_path_rendering) {
14175 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14176 "function not available");
14177 return error::kNoError;
14180 GLuint service_id = 0;
14181 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14182 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14183 "invalid path name");
14184 return error::kNoError;
14187 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14188 if (num_commands < 0) {
14189 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14190 return error::kNoError;
14193 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14194 if (num_coords < 0) {
14195 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14196 return error::kNoError;
14199 GLenum coord_type = static_cast<uint32>(c.coordType);
14200 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14201 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14202 return error::kNoError;
14205 const GLubyte* commands = NULL;
14206 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14208 if (num_commands > 0) {
14209 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14210 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14211 if (commands_shm_id != 0 || commands_shm_offset != 0)
14212 commands = GetSharedMemoryAs<const GLubyte*>(
14213 commands_shm_id, commands_shm_offset, num_commands);
14215 if (!commands)
14216 return error::kOutOfBounds;
14218 for (GLsizei i = 0; i < num_commands; ++i) {
14219 switch (commands[i]) {
14220 case GL_CLOSE_PATH_CHROMIUM:
14221 // Close has no coords.
14222 break;
14223 case GL_MOVE_TO_CHROMIUM:
14224 // Fallthrough.
14225 case GL_LINE_TO_CHROMIUM:
14226 num_coords_expected += 2;
14227 break;
14228 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14229 num_coords_expected += 4;
14230 break;
14231 case GL_CUBIC_CURVE_TO_CHROMIUM:
14232 num_coords_expected += 6;
14233 break;
14234 case GL_CONIC_CURVE_TO_CHROMIUM:
14235 num_coords_expected += 5;
14236 break;
14237 default:
14238 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14239 return error::kNoError;
14244 if (!num_coords_expected.IsValid() ||
14245 num_coords != num_coords_expected.ValueOrDie()) {
14246 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14247 "numCoords does not match commands");
14248 return error::kNoError;
14251 const void* coords = NULL;
14253 if (num_coords > 0) {
14254 uint32 coords_size = 0;
14255 uint32 coord_type_size =
14256 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14257 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14258 return error::kOutOfBounds;
14260 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14261 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14262 if (coords_shm_id != 0 || coords_shm_offset != 0)
14263 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14264 coords_size);
14266 if (!coords)
14267 return error::kOutOfBounds;
14270 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14271 coords);
14273 return error::kNoError;
14276 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14277 uint32 immediate_data_size,
14278 const void* cmd_data) {
14279 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14280 const gles2::cmds::PathParameterfCHROMIUM& c =
14281 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14282 if (!features().chromium_path_rendering) {
14283 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14284 "function not available");
14285 return error::kNoError;
14287 GLuint service_id = 0;
14288 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14289 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14290 "invalid path name");
14291 return error::kNoError;
14294 GLenum pname = static_cast<GLenum>(c.pname);
14295 GLfloat value = static_cast<GLfloat>(c.value);
14296 bool hasValueError = false;
14298 switch (pname) {
14299 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14300 case GL_PATH_MITER_LIMIT_CHROMIUM:
14301 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14302 break;
14303 case GL_PATH_STROKE_BOUND_CHROMIUM:
14304 value = std::max(std::min(1.0f, value), 0.0f);
14305 break;
14306 case GL_PATH_END_CAPS_CHROMIUM:
14307 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14308 static_cast<GLint>(value));
14309 break;
14310 case GL_PATH_JOIN_STYLE_CHROMIUM:
14311 hasValueError = !validators_->path_parameter_join_values.IsValid(
14312 static_cast<GLint>(value));
14313 break;
14314 default:
14315 DCHECK(!validators_->path_parameter.IsValid(pname));
14316 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14317 return error::kNoError;
14319 DCHECK(validators_->path_parameter.IsValid(pname));
14321 if (hasValueError) {
14322 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14323 return error::kNoError;
14326 glPathParameterfNV(service_id, pname, value);
14327 return error::kNoError;
14330 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14331 uint32 immediate_data_size,
14332 const void* cmd_data) {
14333 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14334 const gles2::cmds::PathParameteriCHROMIUM& c =
14335 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14336 if (!features().chromium_path_rendering) {
14337 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14338 "function not available");
14339 return error::kNoError;
14341 GLuint service_id = 0;
14342 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14343 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14344 "invalid path name");
14345 return error::kNoError;
14348 GLenum pname = static_cast<GLenum>(c.pname);
14349 GLint value = static_cast<GLint>(c.value);
14350 bool hasValueError = false;
14352 switch (pname) {
14353 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14354 case GL_PATH_MITER_LIMIT_CHROMIUM:
14355 hasValueError = value < 0;
14356 break;
14357 case GL_PATH_STROKE_BOUND_CHROMIUM:
14358 value = std::max(std::min(1, value), 0);
14359 break;
14360 case GL_PATH_END_CAPS_CHROMIUM:
14361 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14362 break;
14363 case GL_PATH_JOIN_STYLE_CHROMIUM:
14364 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14365 break;
14366 default:
14367 DCHECK(!validators_->path_parameter.IsValid(pname));
14368 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14369 return error::kNoError;
14371 DCHECK(validators_->path_parameter.IsValid(pname));
14373 if (hasValueError) {
14374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14375 return error::kNoError;
14378 glPathParameteriNV(service_id, pname, value);
14379 return error::kNoError;
14382 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14383 uint32 immediate_data_size,
14384 const void* cmd_data) {
14385 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14386 const gles2::cmds::StencilFillPathCHROMIUM& c =
14387 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(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 fill_mode = static_cast<GLenum>(c.fillMode);
14394 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14395 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14396 return error::kNoError;
14398 GLuint mask = static_cast<GLuint>(c.mask);
14399 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14400 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14401 GLES2Util::IsNPOT(mask + 1)) {
14402 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14403 "mask + 1 is not power of two");
14404 return error::kNoError;
14406 GLuint service_id = 0;
14407 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14408 // "If /path/ does not name an existing path object, the command does
14409 // nothing (and no error is generated)."
14410 // This holds for other rendering functions, too.
14411 return error::kNoError;
14413 ApplyDirtyState();
14414 glStencilFillPathNV(service_id, fill_mode, mask);
14415 return error::kNoError;
14418 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14419 uint32 immediate_data_size,
14420 const void* cmd_data) {
14421 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14422 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14423 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14424 if (!features().chromium_path_rendering) {
14425 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14426 "function not available");
14427 return error::kNoError;
14429 GLuint service_id = 0;
14430 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14431 return error::kNoError;
14433 GLint reference = static_cast<GLint>(c.reference);
14434 GLuint mask = static_cast<GLuint>(c.mask);
14435 ApplyDirtyState();
14436 glStencilStrokePathNV(service_id, reference, mask);
14437 return error::kNoError;
14440 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14441 uint32 immediate_data_size,
14442 const void* cmd_data) {
14443 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14444 const gles2::cmds::CoverFillPathCHROMIUM& c =
14445 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14446 if (!features().chromium_path_rendering) {
14447 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14448 "function not available");
14449 return error::kNoError;
14451 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14452 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14453 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14454 return error::kNoError;
14456 GLuint service_id = 0;
14457 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14458 return error::kNoError;
14460 ApplyDirtyState();
14461 glCoverFillPathNV(service_id, cover_mode);
14462 return error::kNoError;
14465 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14466 uint32 immediate_data_size,
14467 const void* cmd_data) {
14468 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14469 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14470 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14471 if (!features().chromium_path_rendering) {
14472 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14473 "function not available");
14474 return error::kNoError;
14476 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14477 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14478 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14479 return error::kNoError;
14481 GLuint service_id = 0;
14482 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14483 return error::kNoError;
14485 ApplyDirtyState();
14486 glCoverStrokePathNV(service_id, cover_mode);
14487 return error::kNoError;
14490 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14491 uint32 immediate_data_size,
14492 const void* cmd_data) {
14493 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14494 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14495 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14496 cmd_data);
14497 if (!features().chromium_path_rendering) {
14498 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14499 "function not available");
14500 return error::kNoError;
14502 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14503 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14504 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14505 return error::kNoError;
14507 GLuint mask = static_cast<GLuint>(c.mask);
14508 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14509 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14510 GLES2Util::IsNPOT(mask + 1)) {
14511 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14512 "mask + 1 is not power of two");
14513 return error::kNoError;
14515 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14516 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14517 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14518 return error::kNoError;
14520 GLuint service_id = 0;
14521 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14522 return error::kNoError;
14524 ApplyDirtyState();
14525 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
14526 return error::kNoError;
14529 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14530 uint32 immediate_data_size,
14531 const void* cmd_data) {
14532 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
14533 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
14534 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
14535 cmd_data);
14536 if (!features().chromium_path_rendering) {
14537 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14538 "function not available");
14539 return error::kNoError;
14541 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14542 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14543 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14544 return error::kNoError;
14546 GLuint service_id = 0;
14547 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14548 return error::kNoError;
14550 GLint reference = static_cast<GLint>(c.reference);
14551 GLuint mask = static_cast<GLuint>(c.mask);
14552 ApplyDirtyState();
14553 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
14554 return error::kNoError;
14557 // Include the auto-generated part of this file. We split this because it means
14558 // we can easily edit the non-auto generated parts right here in this file
14559 // instead of having to edit some template or the code generator.
14560 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14562 } // namespace gles2
14563 } // namespace gpu