| OLD | NEW |
| 1 // Copyright 2010 The Chromium Authors. All rights reserved. | 1 // Copyright 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/output/gl_renderer.h" | 5 #include "cc/output/gl_renderer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "cc/trees/damage_tracker.h" | 33 #include "cc/trees/damage_tracker.h" |
| 34 #include "cc/trees/proxy.h" | 34 #include "cc/trees/proxy.h" |
| 35 #include "cc/trees/single_thread_proxy.h" | 35 #include "cc/trees/single_thread_proxy.h" |
| 36 #include "gpu/GLES2/gl2extchromium.h" | 36 #include "gpu/GLES2/gl2extchromium.h" |
| 37 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3
D.h" | 37 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3
D.h" |
| 38 #include "third_party/khronos/GLES2/gl2.h" | 38 #include "third_party/khronos/GLES2/gl2.h" |
| 39 #include "third_party/khronos/GLES2/gl2ext.h" | 39 #include "third_party/khronos/GLES2/gl2ext.h" |
| 40 #include "third_party/skia/include/core/SkBitmap.h" | 40 #include "third_party/skia/include/core/SkBitmap.h" |
| 41 #include "third_party/skia/include/core/SkColor.h" | 41 #include "third_party/skia/include/core/SkColor.h" |
| 42 #include "third_party/skia/include/core/SkColorFilter.h" | 42 #include "third_party/skia/include/core/SkColorFilter.h" |
| 43 #include "third_party/skia/include/core/SkSurface.h" |
| 43 #include "third_party/skia/include/gpu/GrContext.h" | 44 #include "third_party/skia/include/gpu/GrContext.h" |
| 44 #include "third_party/skia/include/gpu/GrTexture.h" | 45 #include "third_party/skia/include/gpu/GrTexture.h" |
| 45 #include "third_party/skia/include/gpu/SkGpuDevice.h" | 46 #include "third_party/skia/include/gpu/SkGpuDevice.h" |
| 46 #include "third_party/skia/include/gpu/SkGrTexturePixelRef.h" | 47 #include "third_party/skia/include/gpu/SkGrTexturePixelRef.h" |
| 47 #include "ui/gfx/quad_f.h" | 48 #include "ui/gfx/quad_f.h" |
| 48 #include "ui/gfx/rect_conversions.h" | 49 #include "ui/gfx/rect_conversions.h" |
| 49 | 50 |
| 50 using WebKit::WebGraphicsContext3D; | 51 using WebKit::WebGraphicsContext3D; |
| 51 using WebKit::WebGraphicsMemoryAllocation; | 52 using WebKit::WebGraphicsMemoryAllocation; |
| 52 | 53 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 74 bool NeedsIOSurfaceReadbackWorkaround() { | 75 bool NeedsIOSurfaceReadbackWorkaround() { |
| 75 #if defined(OS_MACOSX) | 76 #if defined(OS_MACOSX) |
| 76 // This isn't strictly required in DumpRenderTree-mode when Mesa is used, | 77 // This isn't strictly required in DumpRenderTree-mode when Mesa is used, |
| 77 // but it doesn't seem to hurt. | 78 // but it doesn't seem to hurt. |
| 78 return true; | 79 return true; |
| 79 #else | 80 #else |
| 80 return false; | 81 return false; |
| 81 #endif | 82 #endif |
| 82 } | 83 } |
| 83 | 84 |
| 85 // TODO(enne): move this to SkUtils |
| 86 void ToSkMatrix(SkMatrix* flattened, const gfx::Transform& m) { |
| 87 // Convert from 4x4 to 3x3 by dropping the third row and column. |
| 88 flattened->set(0, SkDoubleToScalar(m.matrix().getDouble(0, 0))); |
| 89 flattened->set(1, SkDoubleToScalar(m.matrix().getDouble(0, 1))); |
| 90 flattened->set(2, SkDoubleToScalar(m.matrix().getDouble(0, 3))); |
| 91 flattened->set(3, SkDoubleToScalar(m.matrix().getDouble(1, 0))); |
| 92 flattened->set(4, SkDoubleToScalar(m.matrix().getDouble(1, 1))); |
| 93 flattened->set(5, SkDoubleToScalar(m.matrix().getDouble(1, 3))); |
| 94 flattened->set(6, SkDoubleToScalar(m.matrix().getDouble(3, 0))); |
| 95 flattened->set(7, SkDoubleToScalar(m.matrix().getDouble(3, 1))); |
| 96 flattened->set(8, SkDoubleToScalar(m.matrix().getDouble(3, 3))); |
| 97 } |
| 98 |
| 84 } // anonymous namespace | 99 } // anonymous namespace |
| 85 | 100 |
| 86 scoped_ptr<GLRenderer> GLRenderer::Create(RendererClient* client, | 101 scoped_ptr<GLRenderer> GLRenderer::Create(RendererClient* client, |
| 87 OutputSurface* output_surface, | 102 OutputSurface* output_surface, |
| 88 ResourceProvider* resource_provider, | 103 ResourceProvider* resource_provider, |
| 89 int highp_threshold_min) { | 104 int highp_threshold_min) { |
| 90 scoped_ptr<GLRenderer> renderer(new GLRenderer( | 105 scoped_ptr<GLRenderer> renderer(new GLRenderer( |
| 91 client, output_surface, resource_provider, highp_threshold_min)); | 106 client, output_surface, resource_provider, highp_threshold_min)); |
| 92 if (!renderer->Initialize()) | 107 if (!renderer->Initialize()) |
| 93 return scoped_ptr<GLRenderer>(); | 108 return scoped_ptr<GLRenderer>(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 106 context_(output_surface->context3d()), | 121 context_(output_surface->context3d()), |
| 107 is_viewport_changed_(false), | 122 is_viewport_changed_(false), |
| 108 is_backbuffer_discarded_(false), | 123 is_backbuffer_discarded_(false), |
| 109 discard_backbuffer_when_not_visible_(false), | 124 discard_backbuffer_when_not_visible_(false), |
| 110 is_using_bind_uniform_(false), | 125 is_using_bind_uniform_(false), |
| 111 visible_(true), | 126 visible_(true), |
| 112 is_scissor_enabled_(false), | 127 is_scissor_enabled_(false), |
| 113 highp_threshold_min_(highp_threshold_min), | 128 highp_threshold_min_(highp_threshold_min), |
| 114 on_demand_tile_raster_resource_id_(0) { | 129 on_demand_tile_raster_resource_id_(0) { |
| 115 DCHECK(context_); | 130 DCHECK(context_); |
| 131 |
| 132 ReinitializeGrContext(); |
| 116 } | 133 } |
| 117 | 134 |
| 118 bool GLRenderer::Initialize() { | 135 bool GLRenderer::Initialize() { |
| 119 if (!context_->makeContextCurrent()) | 136 if (!context_->makeContextCurrent()) |
| 120 return false; | 137 return false; |
| 121 | 138 |
| 122 context_->pushGroupMarkerEXT("CompositorContext"); | 139 context_->pushGroupMarkerEXT("CompositorContext"); |
| 123 | 140 |
| 124 std::string extensions_string = | 141 std::string extensions_string = |
| 125 UTF16ToASCII(context_->getString(GL_EXTENSIONS)); | 142 UTF16ToASCII(context_->getString(GL_EXTENSIONS)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 // Check for texture fast paths. Currently we always use MO8 textures, | 185 // Check for texture fast paths. Currently we always use MO8 textures, |
| 169 // so we only need to avoid POT textures if we have an NPOT fast-path. | 186 // so we only need to avoid POT textures if we have an NPOT fast-path. |
| 170 capabilities_.avoid_pow2_textures = | 187 capabilities_.avoid_pow2_textures = |
| 171 extensions.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0; | 188 extensions.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0; |
| 172 | 189 |
| 173 capabilities_.using_offscreen_context3d = true; | 190 capabilities_.using_offscreen_context3d = true; |
| 174 | 191 |
| 175 is_using_bind_uniform_ = | 192 is_using_bind_uniform_ = |
| 176 extensions.count("GL_CHROMIUM_bind_uniform_location") > 0; | 193 extensions.count("GL_CHROMIUM_bind_uniform_location") > 0; |
| 177 | 194 |
| 178 // Make sure scissoring starts as disabled. | |
| 179 GLC(context_, context_->disable(GL_SCISSOR_TEST)); | |
| 180 DCHECK(!is_scissor_enabled_); | |
| 181 | |
| 182 if (!InitializeSharedObjects()) | 195 if (!InitializeSharedObjects()) |
| 183 return false; | 196 return false; |
| 184 | 197 |
| 185 // Make sure the viewport and context gets initialized, even if it is to zero. | 198 // Make sure the viewport and context gets initialized, even if it is to zero. |
| 186 ViewportChanged(); | 199 ViewportChanged(); |
| 187 return true; | 200 return true; |
| 188 } | 201 } |
| 189 | 202 |
| 190 GLRenderer::~GLRenderer() { | 203 GLRenderer::~GLRenderer() { |
| 191 context_->setMemoryAllocationChangedCallbackCHROMIUM(NULL); | 204 context_->setMemoryAllocationChangedCallbackCHROMIUM(NULL); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 WebKit::WebGraphicsManagedMemoryStats stats; | 242 WebKit::WebGraphicsManagedMemoryStats stats; |
| 230 stats.bytesVisible = bytes_visible; | 243 stats.bytesVisible = bytes_visible; |
| 231 stats.bytesVisibleAndNearby = bytes_visible_and_nearby; | 244 stats.bytesVisibleAndNearby = bytes_visible_and_nearby; |
| 232 stats.bytesAllocated = bytes_allocated; | 245 stats.bytesAllocated = bytes_allocated; |
| 233 stats.backbufferRequested = !is_backbuffer_discarded_; | 246 stats.backbufferRequested = !is_backbuffer_discarded_; |
| 234 context_->sendManagedMemoryStatsCHROMIUM(&stats); | 247 context_->sendManagedMemoryStatsCHROMIUM(&stats); |
| 235 } | 248 } |
| 236 | 249 |
| 237 void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } | 250 void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } |
| 238 | 251 |
| 239 void GLRenderer::ViewportChanged() { is_viewport_changed_ = true; } | 252 void GLRenderer::ViewportChanged() { |
| 253 is_viewport_changed_ = true; |
| 254 ReinitializeGrContext(); |
| 255 } |
| 240 | 256 |
| 241 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { | 257 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { |
| 242 // On DEBUG builds, opaque render passes are cleared to blue to easily see | 258 // On DEBUG builds, opaque render passes are cleared to blue to easily see |
| 243 // regions that were not drawn on the screen. | 259 // regions that were not drawn on the screen. |
| 244 if (frame->current_render_pass->has_transparent_background) | 260 if (frame->current_render_pass->has_transparent_background) |
| 245 GLC(context_, context_->clearColor(0, 0, 0, 0)); | 261 GLC(context_, context_->clearColor(0, 0, 0, 0)); |
| 246 else | 262 else |
| 247 GLC(context_, context_->clearColor(0, 0, 1, 1)); | 263 GLC(context_, context_->clearColor(0, 0, 1, 1)); |
| 248 | 264 |
| 265 bool always_clear = true; |
| 249 #ifdef NDEBUG | 266 #ifdef NDEBUG |
| 250 if (frame->current_render_pass->has_transparent_background) | 267 always_clear = false; |
| 251 #endif | 268 #endif |
| 252 context_->clear(GL_COLOR_BUFFER_BIT); | 269 if (always_clear || frame->current_render_pass->has_transparent_background) { |
| 270 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; |
| 271 if (context_->getContextAttributes().stencil) |
| 272 clear_bits |= GL_STENCIL_BUFFER_BIT; |
| 273 context_->clear(clear_bits); |
| 274 } |
| 253 } | 275 } |
| 254 | 276 |
| 255 void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { | 277 void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { |
| 256 // FIXME: Remove this once backbuffer is automatically recreated on first use | 278 // FIXME: Remove this once backbuffer is automatically recreated on first use |
| 257 EnsureBackbuffer(); | 279 EnsureBackbuffer(); |
| 258 | 280 |
| 259 if (ViewportSize().IsEmpty()) | 281 if (ViewportSize().IsEmpty()) |
| 260 return; | 282 return; |
| 261 | 283 |
| 262 TRACE_EVENT0("cc", "GLRenderer::DrawLayers"); | 284 TRACE_EVENT0("cc", "GLRenderer::DrawLayers"); |
| 263 if (is_viewport_changed_) { | 285 if (is_viewport_changed_) { |
| 264 // Only reshape when we know we are going to draw. Otherwise, the reshape | 286 // Only reshape when we know we are going to draw. Otherwise, the reshape |
| 265 // can leave the window at the wrong size if we never draw and the proper | 287 // can leave the window at the wrong size if we never draw and the proper |
| 266 // viewport size is never set. | 288 // viewport size is never set. |
| 267 is_viewport_changed_ = false; | 289 is_viewport_changed_ = false; |
| 268 output_surface_->Reshape(gfx::Size(ViewportWidth(), ViewportHeight())); | 290 output_surface_->Reshape(gfx::Size(ViewportWidth(), ViewportHeight())); |
| 269 } | 291 } |
| 270 | 292 |
| 271 MakeContextCurrent(); | 293 MakeContextCurrent(); |
| 272 // Bind the common vertex attributes used for drawing all the layers. | |
| 273 shared_geometry_->PrepareForDraw(); | |
| 274 | 294 |
| 275 GLC(context_, context_->disable(GL_DEPTH_TEST)); | 295 ReinitializeGLState(); |
| 276 GLC(context_, context_->disable(GL_CULL_FACE)); | |
| 277 GLC(context_, context_->colorMask(true, true, true, true)); | |
| 278 GLC(context_, context_->enable(GL_BLEND)); | |
| 279 blend_shadow_ = true; | |
| 280 GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); | |
| 281 GLC(Context(), Context()->activeTexture(GL_TEXTURE0)); | |
| 282 program_shadow_ = 0; | |
| 283 } | 296 } |
| 284 | 297 |
| 285 void GLRenderer::DoNoOp() { | 298 void GLRenderer::DoNoOp() { |
| 286 GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0)); | 299 GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
| 287 GLC(context_, context_->flush()); | 300 GLC(context_, context_->flush()); |
| 288 } | 301 } |
| 289 | 302 |
| 290 void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { | 303 void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { |
| 291 DCHECK(quad->rect.Contains(quad->visible_rect)); | 304 DCHECK(quad->rect.Contains(quad->visible_rect)); |
| 292 if (quad->material != DrawQuad::TEXTURE_CONTENT) { | 305 if (quad->material != DrawQuad::TEXTURE_CONTENT) { |
| (...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 Context()->uniform1i(program->fragment_shader().sampler_location(), 0)); | 1437 Context()->uniform1i(program->fragment_shader().sampler_location(), 0)); |
| 1425 | 1438 |
| 1426 SetShaderOpacity(quad->opacity(), | 1439 SetShaderOpacity(quad->opacity(), |
| 1427 program->fragment_shader().alpha_location()); | 1440 program->fragment_shader().alpha_location()); |
| 1428 DrawQuadGeometry(frame, | 1441 DrawQuadGeometry(frame, |
| 1429 quad->quadTransform(), | 1442 quad->quadTransform(), |
| 1430 quad->rect, | 1443 quad->rect, |
| 1431 program->vertex_shader().matrix_location()); | 1444 program->vertex_shader().matrix_location()); |
| 1432 } | 1445 } |
| 1433 | 1446 |
| 1447 void GLRenderer::DrawPictureQuadDirectToBackbuffer( |
| 1448 const DrawingFrame* frame, |
| 1449 const PictureDrawQuad* quad) { |
| 1450 DCHECK(CanUseGanesh()); |
| 1451 |
| 1452 // TODO(enne): Only do this if we've set some state since the last time |
| 1453 // Ganesh drew anything. |
| 1454 gr_context_->get()->resetContext(); |
| 1455 |
| 1456 if (is_scissor_enabled_) { |
| 1457 sk_canvas_->clipRect(gfx::RectToSkRect(scissor_rect_), |
| 1458 SkRegion::kReplace_Op); |
| 1459 } else { |
| 1460 sk_canvas_->clipRect(gfx::RectToSkRect(gfx::Rect(ViewportSize())), |
| 1461 SkRegion::kReplace_Op); |
| 1462 } |
| 1463 |
| 1464 gfx::Transform y_flip; |
| 1465 y_flip.Scale3d(1.0, -1.0, 1.0); |
| 1466 |
| 1467 gfx::Transform contents_device_transform = frame->window_matrix * y_flip * |
| 1468 frame->projection_matrix * quad->quadTransform(); |
| 1469 contents_device_transform.FlattenTo2d(); |
| 1470 SkMatrix sk_device_matrix; |
| 1471 ToSkMatrix(&sk_device_matrix, contents_device_transform); |
| 1472 sk_canvas_->setMatrix(sk_device_matrix); |
| 1473 |
| 1474 quad->picture_pile->Raster(sk_canvas_.get(), |
| 1475 quad->content_rect, |
| 1476 quad->contents_scale); |
| 1477 |
| 1478 ReinitializeGLState(); |
| 1479 } |
| 1480 |
| 1434 void GLRenderer::DrawPictureQuad(const DrawingFrame* frame, | 1481 void GLRenderer::DrawPictureQuad(const DrawingFrame* frame, |
| 1435 const PictureDrawQuad* quad) { | 1482 const PictureDrawQuad* quad) { |
| 1483 if (quad->draw_direct_to_backbuffer && CanUseGanesh()) { |
| 1484 DrawPictureQuadDirectToBackbuffer(frame, quad); |
| 1485 return; |
| 1486 } |
| 1487 |
| 1436 if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() || | 1488 if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() || |
| 1437 on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) { | 1489 on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) { |
| 1438 on_demand_tile_raster_bitmap_.setConfig( | 1490 on_demand_tile_raster_bitmap_.setConfig( |
| 1439 SkBitmap::kARGB_8888_Config, | 1491 SkBitmap::kARGB_8888_Config, |
| 1440 quad->texture_size.width(), | 1492 quad->texture_size.width(), |
| 1441 quad->texture_size.height()); | 1493 quad->texture_size.height()); |
| 1442 on_demand_tile_raster_bitmap_.allocPixels(); | 1494 on_demand_tile_raster_bitmap_.allocPixels(); |
| 1443 | 1495 |
| 1444 if (on_demand_tile_raster_resource_id_) | 1496 if (on_demand_tile_raster_resource_id_) |
| 1445 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); | 1497 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); |
| (...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2566 | 2618 |
| 2567 if (offscreen_framebuffer_id_) | 2619 if (offscreen_framebuffer_id_) |
| 2568 GLC(context_, context_->deleteFramebuffer(offscreen_framebuffer_id_)); | 2620 GLC(context_, context_->deleteFramebuffer(offscreen_framebuffer_id_)); |
| 2569 | 2621 |
| 2570 if (on_demand_tile_raster_resource_id_) | 2622 if (on_demand_tile_raster_resource_id_) |
| 2571 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); | 2623 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); |
| 2572 | 2624 |
| 2573 ReleaseRenderPassTextures(); | 2625 ReleaseRenderPassTextures(); |
| 2574 } | 2626 } |
| 2575 | 2627 |
| 2628 void GLRenderer::ReinitializeGrContext() { |
| 2629 if (!CanUseGanesh()) |
| 2630 return; |
| 2631 |
| 2632 if (!gr_context_) { |
| 2633 gr_context_.reset( |
| 2634 new webkit::gpu::GrContextForWebGraphicsContext3D(context_)); |
| 2635 } |
| 2636 |
| 2637 GrBackendRenderTargetDesc desc; |
| 2638 desc.fWidth = ViewportWidth(); |
| 2639 desc.fHeight = ViewportHeight(); |
| 2640 desc.fConfig = kRGBA_8888_GrPixelConfig; |
| 2641 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; |
| 2642 desc.fSampleCnt = 1; |
| 2643 desc.fStencilBits = 8; |
| 2644 desc.fRenderTargetHandle = 0; |
| 2645 |
| 2646 SkAutoTUnref<GrSurface> surface( |
| 2647 gr_context_->get()->wrapBackendRenderTarget(desc)); |
| 2648 SkAutoTUnref<SkDevice> device(SkGpuDevice::Create(surface)); |
| 2649 sk_canvas_.reset(new SkCanvas(device.get())); |
| 2650 } |
| 2651 |
| 2652 void GLRenderer::ReinitializeGLState() { |
| 2653 // Bind the common vertex attributes used for drawing all the layers. |
| 2654 shared_geometry_->PrepareForDraw(); |
| 2655 |
| 2656 GLC(context_, context_->disable(GL_STENCIL_TEST)); |
| 2657 GLC(context_, context_->disable(GL_DEPTH_TEST)); |
| 2658 GLC(context_, context_->disable(GL_CULL_FACE)); |
| 2659 GLC(context_, context_->colorMask(true, true, true, true)); |
| 2660 GLC(context_, context_->enable(GL_BLEND)); |
| 2661 blend_shadow_ = true; |
| 2662 GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); |
| 2663 GLC(context_, context_->activeTexture(GL_TEXTURE0)); |
| 2664 program_shadow_ = 0; |
| 2665 |
| 2666 // Make sure scissoring starts as disabled. |
| 2667 is_scissor_enabled_ = false; |
| 2668 GLC(context_, context_->disable(GL_SCISSOR_TEST)); |
| 2669 } |
| 2670 |
| 2671 bool GLRenderer::CanUseGanesh() const { |
| 2672 return context_->getContextAttributes().stencil; |
| 2673 } |
| 2674 |
| 2576 bool GLRenderer::IsContextLost() { | 2675 bool GLRenderer::IsContextLost() { |
| 2577 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); | 2676 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); |
| 2578 } | 2677 } |
| 2579 | 2678 |
| 2580 } // namespace cc | 2679 } // namespace cc |
| OLD | NEW |