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 |