Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |