Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/gpu/gl/GrGpuGL.cpp

Issue 13915011: Add support for using glCopyTexSubImage2D when possible to copy surfaces. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/gpu/gl/GrGpuGL.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 8
9 #include "GrGpuGL.h" 9 #include "GrGpuGL.h"
10 #include "GrGLStencilBuffer.h" 10 #include "GrGLStencilBuffer.h"
(...skipping 2211 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 2222
2223 void GrGpuGL::setSpareTextureUnit() { 2223 void GrGpuGL::setSpareTextureUnit() {
2224 if (fHWActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) { 2224 if (fHWActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2225 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); 2225 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
2226 fHWActiveTextureUnitIdx = SPARE_TEX_UNIT; 2226 fHWActiveTextureUnitIdx = SPARE_TEX_UNIT;
2227 } 2227 }
2228 } 2228 }
2229 2229
2230 namespace { 2230 namespace {
2231 // Determines whether glBlitFramebuffer could be used between src and dst. 2231 // Determines whether glBlitFramebuffer could be used between src and dst.
2232 inline bool can_blit_framebuffer(const GrSurface* dst, const GrSurface* src, con st GrGpuGL* gpu) { 2232 inline bool can_blit_framebuffer(const GrSurface* dst,
2233 return gpu->isConfigRenderable(dst->config()) && gpu->isConfigRenderable(src ->config()) && 2233 const GrSurface* src,
2234 (GrGLCaps::kDesktopEXT_MSFBOType == gpu->glCaps().msFBOType() || 2234 const GrGpuGL* gpu,
2235 GrGLCaps::kDesktopARB_MSFBOType == gpu->glCaps().msFBOType()); 2235 bool* wouldNeedTempFBO = NULL) {
2236 if (gpu->isConfigRenderable(dst->config()) && gpu->isConfigRenderable(src->c onfig()) &&
2237 (GrGLCaps::kDesktopEXT_MSFBOType == gpu->glCaps().msFBOType() ||
2238 GrGLCaps::kDesktopARB_MSFBOType == gpu->glCaps().msFBOType())) {
2239 if (NULL != wouldNeedTempFBO) {
2240 *wouldNeedTempFBO = NULL == dst->asRenderTarget() || NULL == src->as RenderTarget();
2241 }
2242 return true;
2243 } else {
2244 return false;
2245 }
2236 } 2246 }
2247
2248 inline bool can_copy_texsubimage(const GrSurface* dst,
2249 const GrSurface* src,
2250 const GrGpuGL* gpu,
2251 bool* wouldNeedTempFBO = NULL) {
2252 // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSub Image
2253 // and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
2254 // many drivers would allow it to work, but ANGLE does not.
2255 if (kES2_GrGLBinding == gpu->glBinding() && gpu->glCaps().bgraIsInternalForm at() &&
2256 (kBGRA_8888_GrPixelConfig == dst->config() || kBGRA_8888_GrPixelConfig = = src->config())) {
2257 return false;
2258 }
2259 const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->as RenderTarget());
2260 // If dst is multisampled (and uses an extension where there is a separate M SAA renderbuffer)
2261 // then we don't want to copy to the texture but to the MSAA buffer.
2262 if (NULL != dstRT && dstRT->renderFBOID() != dstRT->textureFBOID()) {
2263 return false;
2264 }
2265 if (gpu->isConfigRenderable(src->config()) && NULL != dst->asTexture() &&
2266 dst->origin() == src->origin() && kIndex_8_GrPixelConfig != src->config( )) {
2267 if (NULL != wouldNeedTempFBO) {
2268 *wouldNeedTempFBO = NULL == src->asRenderTarget();
2269 }
2270 return true;
2271 } else {
2272 return false;
2273 }
2274 }
2275
robertphillips 2013/04/15 13:01:08 "its (non-zero) ID is returned"?
bsalomon 2013/04/15 13:51:01 Done.
2276 // If a temporary FBO was created, its ID is returned. The viewport that the cop y rect is relative
2277 // to is output.
2278 inline GrGLuint bind_surface_as_fbo(const GrGLInterface* gl,
2279 GrSurface* surface,
2280 GrGLenum fboTarget,
2281 GrGLIRect* viewport) {
2282 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarge t());
2283 GrGLuint tempFBOID;
2284 if (NULL == rt) {
2285 GrAssert(NULL != surface->asTexture());
2286 GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textur eID();
2287 GR_GL_CALL(gl, GenFramebuffers(1, &tempFBOID));
2288 GR_GL_CALL(gl, BindFramebuffer(fboTarget, tempFBOID));
2289 GR_GL_CALL(gl, FramebufferTexture2D(fboTarget,
2290 GR_GL_COLOR_ATTACHMENT0,
2291 GR_GL_TEXTURE_2D,
2292 texID,
2293 0));
robertphillips 2013/04/15 13:01:08 SkIRect::MakeWH?
bsalomon 2013/04/15 13:51:01 It's a GrGLIRect
2294 viewport->fLeft = 0;
2295 viewport->fBottom = 0;
2296 viewport->fWidth = surface->width();
2297 viewport->fHeight = surface->height();
2298 } else {
2299 tempFBOID = 0;
2300 GR_GL_CALL(gl, BindFramebuffer(fboTarget, rt->renderFBOID()));
2301 *viewport = rt->getViewport();
2302 }
2303 return tempFBOID;
2304 }
2305
2306 }
2307
2308 void GrGpuGL::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
2309 // Check for format issues with glCopyTexSubImage2D
2310 if (kES2_GrGLBinding == this->glBinding() && this->glCaps().bgraIsInternalFo rmat() &&
2311 kBGRA_8888_GrPixelConfig == src->config()) {
robertphillips 2013/04/15 13:01:08 I find the 2nd sentence of this comment a bit conf
bsalomon 2013/04/15 13:51:01 // glCopyTexSubImage2D doesn't work with this conf
2312 // glCopyTexSubImage2D doesn't work with this config. We'll want to make it a render target
2313 // either or glBlitFramebuffer or let the base class copy by rendering.
2314 INHERITED::initCopySurfaceDstDesc(src, desc);
2315 } else if (NULL == src->asRenderTarget()) {
2316 // We don't want to have to create an FBO just to use glCopyTexSubImage2 D. Let the base
2317 // class handle it by rendering.
2318 INHERITED::initCopySurfaceDstDesc(src, desc);
2319 } else {
2320 desc->fConfig = src->config();
2321 desc->fOrigin = src->origin();
2322 desc->fFlags = kNone_GrTextureFlags;
2323 }
2237 } 2324 }
2238 2325
2239 bool GrGpuGL::onCopySurface(GrSurface* dst, 2326 bool GrGpuGL::onCopySurface(GrSurface* dst,
2240 GrSurface* src, 2327 GrSurface* src,
2241 const SkIRect& srcRect, 2328 const SkIRect& srcRect,
2242 const SkIPoint& dstPoint) { 2329 const SkIPoint& dstPoint) {
2243 // TODO: Add support for glCopyTexSubImage for cases when src is an FBO and dst is not 2330 bool inheritedCouldCopy = INHERITED::onCanCopySurface(dst, src, srcRect, dst Point);
2244 // renderable or we don't have glBlitFramebuffer.
2245 bool copied = false; 2331 bool copied = false;
2246 // Check whether both src and dst could be attached to an FBO and we're on a GL that supports 2332 bool wouldNeedTempFBO = false;
2247 // glBlitFramebuffer. 2333 if (can_copy_texsubimage(dst, src, this, &wouldNeedTempFBO) &&
2248 if (can_blit_framebuffer(dst, src, this)) { 2334 (!wouldNeedTempFBO || !inheritedCouldCopy)) {
2335 GrGLuint srcFBO;
2336 GrGLIRect srcVP;
2337 srcFBO = bind_surface_as_fbo(this->glInterface(), src, GR_GL_FRAMEBUFFER , &srcVP);
2338 GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture());
2339 GrAssert(NULL != dstTex);
2340 // We modified the bound FBO
2341 fHWBoundRenderTarget = NULL;
2342 GrGLIRect srcGLRect;
2343 srcGLRect.setRelativeTo(srcVP,
2344 srcRect.fLeft,
2345 srcRect.fTop,
2346 srcRect.width(),
2347 srcRect.height(),
2348 src->origin());
2349
2350 this->setSpareTextureUnit();
2351 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, dstTex->textureID()));
2352 GrGLint dstY;
2353 if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
2354 dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
2355 } else {
2356 dstY = dstPoint.fY;
2357 }
2358 GL_CALL(CopyTexSubImage2D(GR_GL_TEXTURE_2D, 0,
2359 dstPoint.fX, dstY,
2360 srcGLRect.fLeft, srcGLRect.fBottom,
2361 srcGLRect.fWidth, srcGLRect.fHeight));
2362 copied = true;
2363 if (srcFBO) {
2364 GL_CALL(DeleteFramebuffers(1, &srcFBO));
2365 }
2366 } else if (can_blit_framebuffer(dst, src, this, &wouldNeedTempFBO) &&
2367 (!wouldNeedTempFBO || !inheritedCouldCopy)) {
2249 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, 2368 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
2250 srcRect.width(), srcRect.height()); 2369 srcRect.width(), srcRect.height());
2251 bool selfOverlap = false; 2370 bool selfOverlap = false;
2252 if (dst->isSameAs(src)) { 2371 if (dst->isSameAs(src)) {
2253 selfOverlap = SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect); 2372 selfOverlap = SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect);
2254 } 2373 }
2255 2374
2256 if (!selfOverlap) { 2375 if (!selfOverlap) {
2257 GrGLuint dstFBO = 0; 2376 GrGLuint dstFBO;
2258 GrGLuint srcFBO = 0; 2377 GrGLuint srcFBO;
2259 GrGLIRect dstVP; 2378 GrGLIRect dstVP;
2260 GrGLIRect srcVP; 2379 GrGLIRect srcVP;
2261 GrGLRenderTarget* dstRT = static_cast<GrGLRenderTarget*>(dst->asRend erTarget()); 2380 dstFBO = bind_surface_as_fbo(this->glInterface(), dst, GR_GL_DRAW_FR AMEBUFFER, &dstVP);
2262 GrGLRenderTarget* srcRT = static_cast<GrGLRenderTarget*>(src->asRend erTarget()); 2381 srcFBO = bind_surface_as_fbo(this->glInterface(), src, GR_GL_READ_FR AMEBUFFER, &srcVP);
2263 if (NULL == dstRT) { 2382 // We modified the bound FBO
2264 GrAssert(NULL != dst->asTexture());
2265 GrGLuint texID = static_cast<GrGLTexture*>(dst->asTexture())->te xtureID();
2266 GL_CALL(GenFramebuffers(1, &dstFBO));
2267 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, dstFBO));
2268 GL_CALL(FramebufferTexture2D(GR_GL_DRAW_FRAMEBUFFER,
2269 GR_GL_COLOR_ATTACHMENT0,
2270 GR_GL_TEXTURE_2D,
2271 texID,
2272 0));
2273 dstVP.fLeft = 0;
2274 dstVP.fBottom = 0;
2275 dstVP.fWidth = dst->width();
2276 dstVP.fHeight = dst->height();
2277 } else {
2278 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, dstRT->renderFBO ID()));
2279 dstVP = dstRT->getViewport();
2280 }
2281 if (NULL == srcRT) {
2282 GrAssert(NULL != src->asTexture());
2283 GrGLuint texID = static_cast<GrGLTexture*>(src->asTexture())->te xtureID();
2284 GL_CALL(GenFramebuffers(1, &srcFBO));
2285 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, srcFBO));
2286 GL_CALL(FramebufferTexture2D(GR_GL_READ_FRAMEBUFFER,
2287 GR_GL_COLOR_ATTACHMENT0,
2288 GR_GL_TEXTURE_2D,
2289 texID,
2290 0));
2291 srcVP.fLeft = 0;
2292 srcVP.fBottom = 0;
2293 srcVP.fWidth = src->width();
2294 srcVP.fHeight = src->height();
2295 } else {
2296 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, srcRT->renderFBO ID()));
2297 srcVP = srcRT->getViewport();
2298 }
2299
2300 // We modified the bound FB
2301 fHWBoundRenderTarget = NULL; 2383 fHWBoundRenderTarget = NULL;
2302 GrGLIRect srcGLRect; 2384 GrGLIRect srcGLRect;
2303 GrGLIRect dstGLRect; 2385 GrGLIRect dstGLRect;
2304 srcGLRect.setRelativeTo(srcVP, 2386 srcGLRect.setRelativeTo(srcVP,
2305 srcRect.fLeft, 2387 srcRect.fLeft,
2306 srcRect.fTop, 2388 srcRect.fTop,
2307 srcRect.width(), 2389 srcRect.width(),
2308 srcRect.height(), 2390 srcRect.height(),
2309 src->origin()); 2391 src->origin());
2310 dstGLRect.setRelativeTo(dstVP, 2392 dstGLRect.setRelativeTo(dstVP,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2342 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); 2424 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
2343 if (dstFBO) { 2425 if (dstFBO) {
2344 GL_CALL(DeleteFramebuffers(1, &dstFBO)); 2426 GL_CALL(DeleteFramebuffers(1, &dstFBO));
2345 } 2427 }
2346 if (srcFBO) { 2428 if (srcFBO) {
2347 GL_CALL(DeleteFramebuffers(1, &srcFBO)); 2429 GL_CALL(DeleteFramebuffers(1, &srcFBO));
2348 } 2430 }
2349 copied = true; 2431 copied = true;
2350 } 2432 }
2351 } 2433 }
2352 if (!copied) { 2434 if (!copied && inheritedCouldCopy) {
2353 copied = INHERITED::onCopySurface(dst, src, srcRect, dstPoint); 2435 copied = INHERITED::onCopySurface(dst, src, srcRect, dstPoint);
2436 GrAssert(copied);
2354 } 2437 }
2355 return copied; 2438 return copied;
2356 } 2439 }
2357 2440
2358 bool GrGpuGL::onCanCopySurface(GrSurface* dst, 2441 bool GrGpuGL::onCanCopySurface(GrSurface* dst,
2359 GrSurface* src, 2442 GrSurface* src,
2360 const SkIRect& srcRect, 2443 const SkIRect& srcRect,
2361 const SkIPoint& dstPoint) { 2444 const SkIPoint& dstPoint) {
2362 // This mirrors the logic in onCopySurface. 2445 // This mirrors the logic in onCopySurface.
2363 bool canBlitFramebuffer = false; 2446 if (can_copy_texsubimage(dst, src, this)) {
2447 return true;
2448 }
2364 if (can_blit_framebuffer(dst, src, this)) { 2449 if (can_blit_framebuffer(dst, src, this)) {
2365 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
2366 srcRect.width(), srcRect.height());
2367 if (dst->isSameAs(src)) { 2450 if (dst->isSameAs(src)) {
2368 canBlitFramebuffer = !SkIRect::IntersectsNoEmptyCheck(dstRect, srcRe ct); 2451 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
2452 srcRect.width(), srcRect.height( ));
2453 if(!SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect)) {
2454 return true;
2455 }
2369 } else { 2456 } else {
2370 canBlitFramebuffer = true; 2457 return true;
2371 } 2458 }
2372 } 2459 }
2373 if (canBlitFramebuffer) { 2460 return INHERITED::onCanCopySurface(dst, src, srcRect, dstPoint);
2374 return true;
2375 } else {
2376 return INHERITED::onCanCopySurface(dst, src, srcRect, dstPoint);
2377 }
2378 } 2461 }
2379 2462
2380 2463
2381 /////////////////////////////////////////////////////////////////////////////// 2464 ///////////////////////////////////////////////////////////////////////////////
2382 2465
2383 GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw( 2466 GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
2384 GrGpuGL* gpu, 2467 GrGpuGL* gpu,
2385 const GrGLVertexBuffer* vbuffer, 2468 const GrGLVertexBuffer* vbuffer,
2386 const GrGLIndexBuffer* ibuffer) { 2469 const GrGLIndexBuffer* ibuffer) {
2387 GrAssert(NULL != vbuffer); 2470 GrAssert(NULL != vbuffer);
(...skipping 16 matching lines...) Expand all
2404 this->setVertexArrayID(gpu, 0); 2487 this->setVertexArrayID(gpu, 0);
2405 } 2488 }
2406 int attrCount = gpu->glCaps().maxVertexAttributes(); 2489 int attrCount = gpu->glCaps().maxVertexAttributes();
2407 if (fDefaultVertexArrayAttribState.count() != attrCount) { 2490 if (fDefaultVertexArrayAttribState.count() != attrCount) {
2408 fDefaultVertexArrayAttribState.resize(attrCount); 2491 fDefaultVertexArrayAttribState.resize(attrCount);
2409 } 2492 }
2410 attribState = &fDefaultVertexArrayAttribState; 2493 attribState = &fDefaultVertexArrayAttribState;
2411 } 2494 }
2412 return attribState; 2495 return attribState;
2413 } 2496 }
OLDNEW
« no previous file with comments | « src/gpu/gl/GrGpuGL.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698