MailboxTextureHolder::MailboxTextureHolder( std::unique_ptr<TextureHolder> textureHolder) { DCHECK(textureHolder->isSkiaTextureHolder()); sk_sp<SkImage> image = textureHolder->skImage(); DCHECK(image); gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl(); GrContext* sharedGrContext = SharedGpuContext::gr(); if (!sharedGrContext) { // Can happen if the context is lost. The SkImage won't be any good now // anyway. return; } GLuint imageTextureId = skia::GrBackendObjectToGrGLTextureInfo(image->getTextureHandle(true)) ->fID; sharedGL->BindTexture(GL_TEXTURE_2D, imageTextureId); sharedGL->GenMailboxCHROMIUM(m_mailbox.name); sharedGL->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM(); sharedGL->Flush(); sharedGL->GenSyncTokenCHROMIUM(fenceSync, m_syncToken.GetData()); sharedGL->BindTexture(GL_TEXTURE_2D, 0); // We changed bound textures in this function, so reset the GrContext. sharedGrContext->resetContext(kTextureBinding_GrGLBackendState); m_size = IntSize(image->width(), image->height()); m_textureId = imageTextureId; m_isConvertedFromSkiaTexture = true; }
static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* data, DeferralMode deferralMode) { RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); if (!context3D) return 0; GrContext* gr = context3D->grContext(); if (!gr) return 0; gr->resetContext(); GrTextureDesc desc; desc.fFlags = kRenderTarget_GrTextureFlagBit; desc.fSampleCnt = 0; desc.fWidth = size.width(); desc.fHeight = size.height(); desc.fConfig = kSkia8888_PM_GrPixelConfig; SkAutoTUnref<GrTexture> texture(gr->createUncachedTexture(desc, 0, 0)); if (!texture.get()) return 0; SkCanvas* canvas; SkAutoTUnref<SkDevice> device(new SkGpuDevice(gr, texture.get())); if (deferralMode == Deferred) { SkAutoTUnref<AcceleratedDeviceContext> deviceContext(new AcceleratedDeviceContext(context3D.get())); canvas = new SkDeferredCanvas(device.get(), deviceContext.get()); } else canvas = new SkCanvas(device.get()); data->m_platformContext.setAccelerated(true); #if USE(ACCELERATED_COMPOSITING) data->m_platformLayer = Canvas2DLayerChromium::create(context3D.release(), size); data->m_platformLayer->setTextureId(texture.get()->getTextureHandle()); data->m_platformLayer->setCanvas(canvas); #endif return canvas; }
static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* data) { RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); if (!context3D) return 0; GrContext* gr = context3D->grContext(); if (!gr) return 0; gr->resetContext(); GrTextureDesc desc; desc.fFlags = kRenderTarget_GrTextureFlagBit; desc.fSampleCnt = 0; desc.fWidth = size.width(); desc.fHeight = size.height(); desc.fConfig = kSkia8888_GrPixelConfig; SkAutoTUnref<GrTexture> texture(gr->createUncachedTexture(desc, 0, 0)); if (!texture.get()) return 0; SkCanvas* canvas; SkAutoTUnref<SkDevice> device(new SkGpuDevice(gr, texture.get())); #if USE(ACCELERATED_COMPOSITING) Canvas2DLayerBridge::ThreadMode threadMode = WebKit::Platform::current()->isThreadedCompositingEnabled() ? Canvas2DLayerBridge::Threaded : Canvas2DLayerBridge::SingleThread; data->m_layerBridge = Canvas2DLayerBridge::create(context3D.release(), size, threadMode, texture.get()->getTextureHandle()); canvas = data->m_layerBridge->skCanvas(device.get()); #else canvas = new SkCanvas(device.get()); #endif data->m_platformContext.setAccelerated(true); return canvas; }
static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const IntSize& size, int msaaSampleCount) { ASSERT(!context3D->webContext()->isContextLost()); GrContext* gr = context3D->grContext(); if (!gr) return 0; gr->resetContext(); SkImageInfo info; info.fWidth = size.width(); info.fHeight = size.height(); info.fColorType = kPMColor_SkColorType; info.fAlphaType = kPremul_SkAlphaType; return adoptRef(SkSurface::NewRenderTarget(gr, info, msaaSampleCount)); }
static SkSurface* createSurface(GraphicsContext3D* context3D, const IntSize& size) { ASSERT(!context3D->webContext()->isContextLost()); GrContext* gr = context3D->grContext(); if (!gr) return 0; gr->resetContext(); SkImage::Info info; info.fWidth = size.width(); info.fHeight = size.height(); info.fColorType = SkImage::kPMColor_ColorType; info.fAlphaType = SkImage::kPremul_AlphaType; return SkSurface::NewRenderTarget(gr, info); }
ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode renderingMode, bool& success) : m_data(size) , m_size(size) , m_accelerateRendering(false) { OwnPtr<SkCanvas> canvas = adoptPtr(skia::TryCreateBitmapCanvas(size.width(), size.height(), false)); if (!canvas) { success = false; return; } m_data.m_canvas = canvas.release(); m_data.m_platformContext.setCanvas(m_data.m_canvas.get()); m_context = adoptPtr(new GraphicsContext(&m_data.m_platformContext)); m_context->platformContext()->setDrawingToImageBuffer(true); // Make the background transparent. It would be nice if this wasn't // required, but the canvas is currently filled with the magic transparency // color. Can we have another way to manage this? m_data.m_canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); if (renderingMode == Accelerated) { GraphicsContext3D* context3D = SharedGraphicsContext3D::create(0); if (context3D) { context3D->makeContextCurrent(); GrContext* gr = context3D->grContext(); if (gr) { gr->resetContext(); GrTextureDesc desc; desc.fFlags = kRenderTarget_GrTextureFlagBit; desc.fAALevel = kNone_GrAALevel; desc.fWidth = size.width(); desc.fHeight = size.height(); desc.fFormat = kRGBA_8888_GrPixelConfig; SkAutoTUnref<GrTexture> texture(gr->createUncachedTexture(desc, 0, 0)); if (texture.get()) { m_data.m_canvas->setDevice(new SkGpuDevice(gr, texture.get()))->unref(); m_context->platformContext()->setGraphicsContext3D(context3D); m_accelerateRendering = true; #if USE(ACCELERATED_COMPOSITING) m_data.m_platformLayer = Canvas2DLayerChromium::create(context3D); m_data.m_platformLayer->setTextureId(texture.get()->getTextureHandle()); #endif } } } } success = true; }
void SKPBench::getGpuStats(SkCanvas* canvas, SkTArray<SkString>* keys, SkTArray<double>* values) { #if SK_SUPPORT_GPU // we do a special single draw and then dump the key / value pairs GrContext* context = canvas->getGrContext(); if (!context) { return; } // TODO refactor this out if we want to test other subclasses of skpbench context->flush(); context->freeGpuResources(); context->resetContext(); context->getGpu()->resetShaderCacheForTesting(); draw_pic_for_stats(canvas, context, fPic, keys, values, "first_frame"); // draw second frame draw_pic_for_stats(canvas, context, fPic, keys, values, "second_frame"); #endif }
void LayerTextureUpdaterSkPicture::updateTextureRect(GraphicsContext3D* compositorContext, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect) { ASSERT(!m_context || m_context == compositorContext); m_context = compositorContext; if (m_createFrameBuffer) { deleteFrameBuffer(); createFrameBuffer(); m_createFrameBuffer = false; } if (!m_fbo) return; // Bind texture. context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); texture->framebufferTexture2D(context(), allocator); ASSERT(context()->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE); // Make sure SKIA uses the correct GL context. context()->makeContextCurrent(); GrContext* skiaContext = m_context->grContext(); // Notify SKIA to sync its internal GL state. skiaContext->resetContext(); m_canvas->save(); m_canvas->clipRect(SkRect(destRect)); // Translate the origin of contentRect to that of destRect. // Note that destRect is defined relative to sourceRect. m_canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(), contentRect().y() - sourceRect.y() + destRect.y()); m_canvas->drawPicture(m_picture); m_canvas->restore(); // Flush SKIA context so that all the rendered stuff appears on the texture. skiaContext->flush(); // Unbind texture. context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0); context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); }
bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap) { ASSERT(isAccelerated()); if (m_destructionInProgress) { // It can be hit in the following sequence. // 1. Canvas draws something. // 2. The compositor begins the frame. // 3. Javascript makes a context be lost. // 4. Here. return false; } if (bitmap) { // Using accelerated 2d canvas with software renderer, which // should only happen in tests that use fake graphics contexts // or in Android WebView in software mode. In this case, we do // not care about producing any results for this canvas. skipQueuedDrawCommands(); m_lastImageId = 0; return false; } if (!checkSurfaceValid()) return false; WebGraphicsContext3D* webContext = context(); RefPtr<SkImage> image = newImageSnapshot(PreferAcceleration); // Early exit if canvas was not drawn to since last prepareMailbox GLenum filter = m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR; if (image->uniqueID() == m_lastImageId && filter == m_lastFilter) return false; m_lastImageId = image->uniqueID(); m_lastFilter = filter; { MailboxInfo tmp; tmp.m_image = image; tmp.m_parentLayerBridge = this; m_mailboxes.prepend(tmp); } MailboxInfo& mailboxInfo = m_mailboxes.first(); mailboxInfo.m_mailbox.nearestNeighbor = filter == GL_NEAREST; GrContext* grContext = m_contextProvider->grContext(); if (!grContext) return true; // for testing: skip gl stuff when using a mock graphics context. // Need to flush skia's internal queue because texture is about to be accessed directly grContext->flush(); ASSERT(image->getTexture()); // Because of texture sharing with the compositor, we must invalidate // the state cached in skia so that the deferred copy on write // in SkSurface_Gpu does not make any false assumptions. mailboxInfo.m_image->getTexture()->textureParamsModified(); webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo.m_image->getTexture()->getTextureHandle()); webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Re-use the texture's existing mailbox, if there is one. if (image->getTexture()->getCustomData()) { ASSERT(image->getTexture()->getCustomData()->size() == sizeof(mailboxInfo.m_mailbox.name)); memcpy(&mailboxInfo.m_mailbox.name[0], image->getTexture()->getCustomData()->data(), sizeof(mailboxInfo.m_mailbox.name)); } else { context()->genMailboxCHROMIUM(mailboxInfo.m_mailbox.name); RefPtr<SkData> mailboxNameData = adoptRef(SkData::NewWithCopy(&mailboxInfo.m_mailbox.name[0], sizeof(mailboxInfo.m_mailbox.name))); image->getTexture()->setCustomData(mailboxNameData.get()); webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo.m_mailbox.name); } if (isHidden()) { // With hidden canvases, we release the SkImage immediately because // there is no need for animations to be double buffered. mailboxInfo.m_image.clear(); } else { // FIXME: We'd rather insert a syncpoint than perform a flush here, // but currentlythe canvas will flicker if we don't flush here. webContext->flush(); // mailboxInfo.m_mailbox.syncPoint = webContext->insertSyncPoint(); } webContext->bindTexture(GL_TEXTURE_2D, 0); // Because we are changing the texture binding without going through skia, // we must dirty the context. grContext->resetContext(kTextureBinding_GrGLBackendState); *outMailbox = mailboxInfo.m_mailbox; return true; }
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) { GrContext* context = ctxInfo.grContext(); sk_gpu_test::GLTestContext* glContext = ctxInfo.glContext(); static const int kWidth = 13; static const int kHeight = 13; GrColor pixels[kWidth * kHeight]; for (int y = 0; y < kHeight; ++y) { for (int x = 0; x < kWidth; ++x) { pixels[y * kWidth + x] = y * kWidth + x; } } for (int origin = 0; origin < 2; ++origin) { GrGLuint rectTexID = glContext->createTextureRectangle(kWidth, kHeight, GR_GL_RGBA, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels); if (!rectTexID) { return; } // Let GrContext know that we messed with the GL context directly. context->resetContext(); // Wrap the rectangle texture ID in a GrTexture GrGLTextureInfo rectangleInfo; rectangleInfo.fID = rectTexID; rectangleInfo.fTarget = GR_GL_TEXTURE_RECTANGLE; GrBackendTextureDesc rectangleDesc; rectangleDesc.fFlags = kRenderTarget_GrBackendTextureFlag; rectangleDesc.fConfig = kRGBA_8888_GrPixelConfig; rectangleDesc.fWidth = kWidth; rectangleDesc.fHeight = kHeight; rectangleDesc.fOrigin = origin ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin; rectangleDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&rectangleInfo); GrColor refPixels[kWidth * kHeight]; bool flipRef = rectangleDesc.fOrigin == kBottomLeft_GrSurfaceOrigin; for (int y = 0; y < kHeight; ++y) { for (int x = 0; x < kWidth; ++x) { int y0 = flipRef ? kHeight - y - 1 : y; refPixels[y * kWidth + x] = pixels[y0 * kWidth + x]; } } SkAutoTUnref<GrTexture> rectangleTexture( context->textureProvider()->wrapBackendTexture(rectangleDesc)); if (!rectangleTexture) { ERRORF(reporter, "Error wrapping rectangle texture in GrTexture."); GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID)); continue; } test_read_pixels(reporter, context, rectangleTexture, refPixels); test_copy_surface_src(reporter, context, rectangleTexture, refPixels); test_copy_surface_dst(reporter, context, rectangleTexture); test_write_pixels(reporter, context, rectangleTexture); test_clear(reporter, context, rectangleTexture); GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID)); } }
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) { GrContext* context = ctxInfo.grContext(); GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); sk_gpu_test::GLTestContext* glContext = ctxInfo.glContext(); static const int kWidth = 13; static const int kHeight = 13; GrColor pixels[kWidth * kHeight]; for (int y = 0; y < kHeight; ++y) { for (int x = 0; x < kWidth; ++x) { pixels[y * kWidth + x] = y * kWidth + x; } } for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) { bool useBLOrigin = kBottomLeft_GrSurfaceOrigin == origin; GrGLuint rectTexID = glContext->createTextureRectangle(kWidth, kHeight, GR_GL_RGBA, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels); if (!rectTexID) { return; } // Let GrContext know that we messed with the GL context directly. context->resetContext(); // Wrap the rectangle texture ID in a GrTexture GrGLTextureInfo rectangleInfo; rectangleInfo.fID = rectTexID; rectangleInfo.fTarget = GR_GL_TEXTURE_RECTANGLE; GrBackendTexture rectangleTex(kWidth, kHeight, kRGBA_8888_GrPixelConfig, rectangleInfo); GrColor refPixels[kWidth * kHeight]; for (int y = 0; y < kHeight; ++y) { for (int x = 0; x < kWidth; ++x) { int y0 = useBLOrigin ? kHeight - y - 1 : y; refPixels[y * kWidth + x] = pixels[y0 * kWidth + x]; } } sk_sp<GrTextureProxy> rectProxy = proxyProvider->wrapBackendTexture(rectangleTex, origin); if (!rectProxy) { ERRORF(reporter, "Error creating proxy for rectangle texture."); GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID)); continue; } SkASSERT(rectProxy->texPriv().doesNotSupportMipMaps()); SkASSERT(rectProxy->priv().peekTexture()->surfacePriv().doesNotSupportMipMaps()); SkASSERT(rectProxy->texPriv().isClampOnly()); SkASSERT(rectProxy->priv().peekTexture()->surfacePriv().isClampOnly()); test_basic_draw_as_src(reporter, context, rectProxy, refPixels); // Test copy to both a texture and RT test_copy_from_surface(reporter, context, rectProxy.get(), refPixels, false, "RectangleTexture-copy-from"); sk_sp<GrSurfaceContext> rectContext = context->contextPriv().makeWrappedSurfaceContext( std::move(rectProxy)); SkASSERT(rectContext); test_read_pixels(reporter, rectContext.get(), refPixels, "RectangleTexture-read"); test_copy_to_surface(reporter, context->contextPriv().proxyProvider(), rectContext.get(), "RectangleTexture-copy-to"); test_write_pixels(reporter, rectContext.get(), true, "RectangleTexture-write"); test_clear(reporter, rectContext.get()); GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID)); } }