void ContentLayerChromium::draw() { if (m_skipsDraw) return; ASSERT(layerRenderer()); const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues(); ASSERT(sv && sv->initialized()); GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture)); layerRenderer()->useShader(sv->contentShaderProgram()); GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); if (requiresClippedUpdateRect()) { float m43 = drawTransform().m43(); TransformationMatrix transform; transform.translate3d(m_largeLayerDrawRect.center().x(), m_largeLayerDrawRect.center().y(), m43); drawTexturedQuad(context, layerRenderer()->projectionMatrix(), transform, m_largeLayerDrawRect.width(), m_largeLayerDrawRect.height(), drawOpacity(), sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); } else { drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), m_bounds.width(), m_bounds.height(), drawOpacity(), sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); } }
RenderSurfaceChromium::SharedValues::~SharedValues() { if (m_shaderProgram) GLC(m_context, m_context->deleteProgram(m_shaderProgram)); if (m_maskShaderProgram) GLC(m_context, m_context->deleteProgram(m_maskShaderProgram)); }
void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId) { if (!pixels) return; GraphicsContext3D* context = layerRendererContext(); context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); // If the texture id or size changed since last time then we need to tell GL // to re-allocate a texture. if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize) { ASSERT(bitmapSize == requiredTextureSize); GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); m_contentsTexture = textureId; m_allocatedTextureSize = requiredTextureSize; } else { ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height()); ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height()); GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); } m_dirtyRect.setSize(FloatSize()); // Large layers always stay dirty, because they need to update when the content rect changes. m_contentsDirty = requiresClippedUpdateRect(); }
VideoLayerChromium::SharedValues::~SharedValues() { if (m_yuvShaderProgram) GLC(m_context, m_context->deleteProgram(m_yuvShaderProgram)); if (m_rgbaShaderProgram) GLC(m_context, m_context->deleteProgram(m_rgbaShaderProgram)); }
void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMatrix, float width, float height, float opacity, const FloatQuad& quad, int matrixLocation, int alphaLocation, int quadLocation) { static float glMatrix[16]; TransformationMatrix renderMatrix = drawMatrix; // Apply a scaling factor to size the quad from 1x1 to its intended size. renderMatrix.scale3d(width, height, 1); // Apply the projection matrix before sending the transform over to the shader. toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix); GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1)); if (quadLocation != -1) { float point[8]; point[0] = quad.p1().x(); point[1] = quad.p1().y(); point[2] = quad.p2().x(); point[3] = quad.p2().y(); point[4] = quad.p3().x(); point[5] = quad.p3().y(); point[6] = quad.p4().x(); point[7] = quad.p4().y(); GLC(m_context, m_context->uniform2fv(quadLocation, point, 4)); } if (alphaLocation != -1) GLC(m_context, m_context->uniform1f(alphaLocation, opacity)); GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); }
bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface) { if (m_currentRenderSurface == renderSurface) return true; m_currentRenderSurface = renderSurface; if ((renderSurface == m_defaultRenderSurface && !settings().compositeOffscreen) || (!renderSurface && settings().compositeOffscreen)) { GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); if (renderSurface) setDrawViewportRect(renderSurface->contentRect(), true); else setDrawViewportRect(m_defaultRenderSurface->contentRect(), true); return true; } GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); if (!renderSurface->prepareContentsTexture(this)) return false; renderSurface->contentsTexture()->framebufferTexture2D(m_context.get(), m_renderSurfaceTextureAllocator.get()); #if !defined ( NDEBUG ) if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { ASSERT_NOT_REACHED(); return false; } #endif setDrawViewportRect(renderSurface->contentRect(), false); return true; }
void TiledLayerChromium::updateCompositorResources(GraphicsContext3D* context) { // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update. if (m_skipsDraw || m_updateRect.isEmpty() || !m_tiler->numTiles()) return; int left, top, right, bottom; m_tiler->contentRectToTileIndices(m_updateRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); else if (!tile->dirty()) continue; // Calculate page-space rectangle to copy from. IntRect sourceRect = m_tiler->tileContentRect(tile); const IntPoint anchor = sourceRect.location(); sourceRect.intersect(m_tiler->layerRectToContentRect(tile->m_dirtyLayerRect)); // Paint rect not guaranteed to line up on tile boundaries, so // make sure that sourceRect doesn't extend outside of it. sourceRect.intersect(m_paintRect); if (sourceRect.isEmpty()) continue; ASSERT(tile->texture()->isReserved()); // Calculate tile-space rectangle to upload into. IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size()); if (destRect.x() < 0) CRASH(); if (destRect.y() < 0) CRASH(); // Offset from paint rectangle to this tile's dirty rectangle. IntPoint paintOffset(sourceRect.x() - m_paintRect.x(), sourceRect.y() - m_paintRect.y()); if (paintOffset.x() < 0) CRASH(); if (paintOffset.y() < 0) CRASH(); if (paintOffset.x() + destRect.width() > m_paintRect.width()) CRASH(); if (paintOffset.y() + destRect.height() > m_paintRect.height()) CRASH(); tile->texture()->bindTexture(context); const GC3Dint filter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST; GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, filter)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, filter)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0)); textureUpdater()->updateTextureRect(context, tile->texture(), sourceRect, destRect); tile->clearDirty(); } } }
CCResourceProvider::ResourceId CCResourceProvider::createResource(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint) { ASSERT(CCProxy::isImplThread()); unsigned textureId = 0; WebGraphicsContext3D* context3d = m_context->context3D(); if (!context3d) { // FIXME: Implement this path for software compositing. return 0; } GLC(context3d, textureId = context3d->createTexture()); GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); if (m_useTextureUsageHint && hint == TextureUsageFramebuffer) GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, Extensions3DChromium::GL_TEXTURE_USAGE_ANGLE, Extensions3DChromium::GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) { GC3Denum storageFormat = textureToStorageFormat(format); GLC(context3d, context3d->texStorage2DEXT(GraphicsContext3D::TEXTURE_2D, 1, storageFormat, size.width(), size.height())); } else GLC(context3d, context3d->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE, 0)); ResourceId id = m_nextId++; Resource resource = {textureId, pool, 0, false, false, size, format}; m_resources.add(id, resource); return id; }
void CanvasLayerChromium::draw() { ASSERT(layerRenderer()); const CanvasLayerChromium::SharedValues* sv = layerRenderer()->canvasLayerSharedValues(); ASSERT(sv && sv->initialized()); GLC(glActiveTexture(GL_TEXTURE0)); GLC(glBindTexture(GL_TEXTURE_2D, m_textureId)); layerRenderer()->useShader(sv->canvasShaderProgram()); GLC(glUniform1i(sv->shaderSamplerLocation(), 0)); drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); }
void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) { ASSERT(context); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); void* mem = static_cast<Extensions3DChromium*>(context->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY); if (mem) { memcpy(mem, data, dimensions.width() * dimensions.height()); GLC(context, static_cast<Extensions3DChromium*>(context->getExtensions())->unmapTexSubImage2DCHROMIUM(mem)); } else { // FIXME: We should have some sort of code to handle the case when // mapTexSubImage2D fails. m_skipsDraw = true; } }
void CCRenderSurface::draw(LayerRendererChromium* layerRenderer, const FloatRect& surfaceDamageRect) { if (m_skipsDraw || !m_contentsTexture) return; // FIXME: By using the same RenderSurface for both the content and its reflection, // it's currently not possible to apply a separate mask to the reflection layer // or correctly handle opacity in reflections (opacity must be applied after drawing // both the layer and its reflection). The solution is to introduce yet another RenderSurface // to draw the layer and its reflection in. For now we only apply a separate reflection // mask if the contents don't have a mask of their own. CCLayerImpl* replicaMaskLayer = m_maskLayer; if (!m_maskLayer && m_owningLayer->replicaLayer()) replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer(); if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping() && layerRenderer->capabilities().usingPartialSwap) { FloatRect clipAndDamageRect = m_clipRect; clipAndDamageRect.intersect(surfaceDamageRect); layerRenderer->setScissorToRect(enclosingIntRect(clipAndDamageRect)); } else if (layerRenderer->capabilities().usingPartialSwap) layerRenderer->setScissorToRect(enclosingIntRect(surfaceDamageRect)); else if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping()) layerRenderer->setScissorToRect(m_clipRect); else GLC(layerRenderer->context(), layerRenderer->context()->disable(GraphicsContext3D::SCISSOR_TEST)); // Reflection draws before the layer. if (m_owningLayer->replicaLayer()) drawLayer(layerRenderer, replicaMaskLayer, m_replicaDrawTransform); drawLayer(layerRenderer, m_maskLayer, m_drawTransform); }
void LayerTextureSubImage::uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset, GC3Denum format, WebGraphicsContext3D* context) { TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithMapTexSubImage"); // Offset from image-rect to source-rect. IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); // Upload tile data via a mapped transfer buffer uint8_t* pixelDest = static_cast<uint8_t*>(context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY)); if (!pixelDest) { uploadWithTexSubImage(image, imageRect, sourceRect, destOffset, format, context); return; } unsigned int componentsPerPixel; unsigned int bytesPerComponent; if (!GraphicsContext3D::computeFormatAndTypeParameters(format, GraphicsContext3D::UNSIGNED_BYTE, &componentsPerPixel, &bytesPerComponent)) { ASSERT_NOT_REACHED(); return; } if (imageRect.width() == sourceRect.width() && !offset.x()) memcpy(pixelDest, &image[offset.y() * imageRect.width() * componentsPerPixel * bytesPerComponent], imageRect.width() * sourceRect.height() * componentsPerPixel * bytesPerComponent); else { // Strides not equal, so do a row-by-row memcpy from the // paint results into the pixelDest for (int row = 0; row < sourceRect.height(); ++row) memcpy(&pixelDest[sourceRect.width() * row * componentsPerPixel * bytesPerComponent], &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], sourceRect.width() * componentsPerPixel * bytesPerComponent); } GLC(context, context->unmapTexSubImage2DCHROMIUM(pixelDest)); }
void LayerRendererChromium::useShader(unsigned programId) { if (programId != m_currentShader) { GLC(glUseProgram(programId)); m_currentShader = programId; } }
void LayerRendererChromium::useShader(unsigned programId) { if (programId != m_currentShader) { GLC(m_context.get(), m_context->useProgram(programId)); m_currentShader = programId; } }
void LayerRendererChromium::deleteLayerTexture(unsigned textureId) { if (!textureId) return; GLC(m_context.get(), m_context->deleteTexture(textureId)); }
void LayerTextureSubImage::uploadWithTexSubImage(const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset, GC3Denum format, WebGraphicsContext3D* context) { TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithTexSubImage"); // Offset from image-rect to source-rect. IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); const uint8_t* pixelSource; if (imageRect.width() == sourceRect.width() && !offset.x()) pixelSource = &image[4 * offset.y() * imageRect.width()]; else { size_t neededSize = 4 * sourceRect.width() * sourceRect.height(); if (m_subImageSize < neededSize) { m_subImage = adoptArrayPtr(new uint8_t[neededSize]); m_subImageSize = neededSize; } // Strides not equal, so do a row-by-row memcpy from the // paint results into a temp buffer for uploading. for (int row = 0; row < sourceRect.height(); ++row) memcpy(&m_subImage[sourceRect.width() * 4 * row], &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], sourceRect.width() * 4); pixelSource = &m_subImage[0]; } GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, pixelSource)); }
bool LayerRendererChromium::initialize() { m_context->makeContextCurrent(); if (settings().acceleratePainting) m_capabilities.usingAcceleratedPainting = true; WebCore::Extensions3D* extensions = m_context->getExtensions(); m_capabilities.usingMapSub = extensions->supports("GL_CHROMIUM_map_sub"); if (m_capabilities.usingMapSub) extensions->ensureEnabled("GL_CHROMIUM_map_sub"); // Use the swapBuffers callback only with the threaded proxy. if (settings().enableCompositorThread) m_capabilities.usingSwapCompleteCallback = extensions->supports("GL_CHROMIUM_swapbuffers_complete_callback"); if (m_capabilities.usingSwapCompleteCallback) { extensions->ensureEnabled("GL_CHROMIUM_swapbuffers_complete_callback"); Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions); extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(LayerRendererSwapBuffersCompleteCallbackAdapter::create(this)); } if (extensions->supports("GL_EXT_texture_format_BGRA8888")) extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888"); GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize)); m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get()); if (!initializeSharedObjects()) return false; m_headsUpDisplay = CCHeadsUpDisplay::create(this); // Make sure the viewport and context gets initialized, even if it is to zero. viewportChanged(); return true; }
bool CCResourceProvider::initialize() { ASSERT(CCProxy::isImplThread()); WebGraphicsContext3D* context3d = m_context->context3D(); if (!context3d || !context3d->makeContextCurrent()) { // FIXME: Implement this path for software compositing. return false; } WebKit::WebString extensionsWebString = context3d->getString(GraphicsContext3D::EXTENSIONS); String extensionsString(extensionsWebString.data(), extensionsWebString.length()); Vector<String> extensions; extensionsString.split(' ', extensions); bool useMapSub = false; for (size_t i = 0; i < extensions.size(); ++i) { if (extensions[i] == "GL_EXT_texture_storage") m_useTextureStorageExt = true; else if (extensions[i] == "GL_ANGLE_texture_usage") m_useTextureUsageHint = true; else if (extensions[i] == "GL_CHROMIUM_map_sub") useMapSub = true; else if (extensions[i] == "GL_CHROMIUM_shallow_flush") m_useShallowFlush = true; } m_texSubImage = adoptPtr(new LayerTextureSubImage(useMapSub)); GLC(context3d, context3d->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); return true; }
void ContentLayerChromium::draw() { if (m_skipsDraw) return; ASSERT(layerRenderer()); const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues(); ASSERT(sv && sv->initialized()); GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture)); layerRenderer()->useShader(sv->contentShaderProgram()); GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); }
// Sets the coordinate range of content that ends being drawn onto the target render surface. // The target render surface is assumed to have an origin at 0, 0 and the width and height of // of the drawRect. void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY) { if (flipY) m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y()); else m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY()); GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height())); }
ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) : m_context(context) , m_contentShaderProgram(0) , m_shaderSamplerLocation(-1) , m_shaderMatrixLocation(-1) , m_shaderAlphaLocation(-1) , m_initialized(false) , m_npotSupported(false) { // Shaders for drawing the layer contents. char vertexShaderString[] = "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" "uniform mat4 matrix; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " gl_Position = matrix * a_position; \n" " v_texCoord = a_texCoord; \n" "} \n"; // Note differences between Skia and Core Graphics versions: // - Skia uses BGRA // - Core Graphics uses RGBA char fragmentShaderString[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" "uniform float alpha; \n" "void main() \n" "{ \n" " vec4 texColor = texture2D(s_texture, v_texCoord); \n" #if PLATFORM(SKIA) " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n" #elif PLATFORM(CG) " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" #else #error "Need to implement for your platform." #endif "} \n"; m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); if (!m_contentShaderProgram) { LOG_ERROR("ContentLayerChromium: Failed to create shader program"); return; } m_shaderSamplerLocation = m_context->getUniformLocation(m_contentShaderProgram, "s_texture"); m_shaderMatrixLocation = m_context->getUniformLocation(m_contentShaderProgram, "matrix"); m_shaderAlphaLocation = m_context->getUniformLocation(m_contentShaderProgram, "alpha"); ASSERT(m_shaderSamplerLocation != -1); ASSERT(m_shaderMatrixLocation != -1); ASSERT(m_shaderAlphaLocation != -1); m_npotSupported = GLC(context, context->getString(GraphicsContext3D::EXTENSIONS).contains("GL_OES_texture_npot")); m_initialized = true; }
Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, const IntSize& size, DeferralMode deferralMode, unsigned textureId) : m_deferralMode(deferralMode) // FIXME: We currently turn off double buffering when canvas rendering is // deferred. What we should be doing is to use a smarter heuristic based // on GPU resource monitoring and other factors to chose between single // and double buffering. , m_useDoubleBuffering(CCProxy::hasImplThread() && deferralMode == NonDeferred) , m_frontBufferTexture(0) , m_backBufferTexture(textureId) , m_size(size) , m_canvas(0) , m_context(context) { if (m_useDoubleBuffering) { m_context->makeContextCurrent(); GLC(m_context.get(), m_frontBufferTexture = m_context->createTexture()); GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_frontBufferTexture)); // Do basic linear filtering on resize. GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE. GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE)); if (GrContext* grContext = m_context->grContext()) grContext->resetContext(); } m_layer = WebExternalTextureLayer::create(this); m_layer.setTextureId(textureId); m_layer.setRateLimitContext(!CCProxy::hasImplThread() || m_useDoubleBuffering); }
unsigned TextureManager::requestTexture(TextureToken token, IntSize size, unsigned format, bool* newTexture) { if (size.width() > m_maxTextureSize || size.height() > m_maxTextureSize) return 0; TextureMap::iterator it = m_textures.find(token); if (it != m_textures.end()) { ASSERT(it->second.size != size || it->second.format != format); removeTexture(token, it->second); } size_t memoryRequiredBytes = memoryUseBytes(size, format); if (memoryRequiredBytes > m_memoryLimitBytes || !reduceMemoryToLimit(m_memoryLimitBytes - memoryRequiredBytes)) return 0; unsigned textureId = m_context->createTexture(); GLC(m_context.get(), textureId = m_context->createTexture()); GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); // Do basic linear filtering on resize. GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE. GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE)); TextureInfo info; info.size = size; info.format = format; info.textureId = textureId; info.isProtected = true; addTexture(token, info); return textureId; }
void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform, const TransformationMatrix& deviceTransform, const CCLayerQuad& deviceRect, const CCLayerQuad& layerQuad, int contentsTextureId, const T* program, int shaderMaskSamplerLocation, int shaderQuadLocation, int shaderEdgeLocation) { GraphicsContext3D* context3D = layerRenderer->context(); context3D->makeContextCurrent(); GLC(context3D, context3D->useProgram(program->program())); GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context3D, context3D->uniform1i(program->fragmentShader().samplerLocation(), 0)); context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId); if (shaderMaskSamplerLocation != -1) { GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1)); GLC(context3D, context3D->uniform1i(shaderMaskSamplerLocation, 1)); maskLayer->bindContentsTexture(layerRenderer); GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0)); } if (shaderEdgeLocation != -1) { float edge[24]; layerQuad.toFloatArray(edge); deviceRect.toFloatArray(&edge[12]); GLC(context3D, context3D->uniform3fv(shaderEdgeLocation, 8, edge)); } // Map device space quad to layer space. FloatQuad quad = deviceTransform.inverse().mapQuad(layerQuad.floatQuad()); layerRenderer->drawTexturedQuad(drawTransform, m_contentRect.width(), m_contentRect.height(), m_drawOpacity, quad, program->vertexShader().matrixLocation(), program->fragmentShader().alphaLocation(), shaderQuadLocation); }
void LayerRendererChromium::cleanupSharedObjects() { makeContextCurrent(); m_layerSharedValues.clear(); m_contentLayerSharedValues.clear(); m_canvasLayerSharedValues.clear(); if (m_scrollShaderProgram) { GLC(glDeleteProgram(m_scrollShaderProgram)); m_scrollShaderProgram = 0; } if (m_rootLayerTextureId) { GLC(glDeleteTextures(1, &m_rootLayerTextureId)); m_rootLayerTextureId = 0; } }
void LayerRendererChromium::cleanupSharedObjects() { makeContextCurrent(); m_sharedGeometry.clear(); if (m_borderProgram) m_borderProgram->cleanup(m_context.get()); if (m_headsUpDisplayProgram) m_headsUpDisplayProgram->cleanup(m_context.get()); if (m_tilerProgram) m_tilerProgram->cleanup(m_context.get()); if (m_tilerProgramAA) m_tilerProgramAA->cleanup(m_context.get()); if (m_tilerProgramSwizzle) m_tilerProgramSwizzle->cleanup(m_context.get()); if (m_tilerProgramSwizzleAA) m_tilerProgramSwizzleAA->cleanup(m_context.get()); if (m_canvasLayerProgram) m_canvasLayerProgram->cleanup(m_context.get()); if (m_pluginLayerProgram) m_pluginLayerProgram->cleanup(m_context.get()); if (m_pluginLayerProgramFlip) m_pluginLayerProgramFlip->cleanup(m_context.get()); if (m_renderSurfaceMaskProgram) m_renderSurfaceMaskProgram->cleanup(m_context.get()); if (m_renderSurfaceMaskProgramAA) m_renderSurfaceMaskProgramAA->cleanup(m_context.get()); if (m_renderSurfaceProgram) m_renderSurfaceProgram->cleanup(m_context.get()); if (m_renderSurfaceProgramAA) m_renderSurfaceProgramAA->cleanup(m_context.get()); if (m_videoLayerRGBAProgram) m_videoLayerRGBAProgram->cleanup(m_context.get()); if (m_videoLayerYUVProgram) m_videoLayerYUVProgram->cleanup(m_context.get()); m_borderProgram.clear(); m_headsUpDisplayProgram.clear(); m_tilerProgram.clear(); m_tilerProgramAA.clear(); m_tilerProgramSwizzle.clear(); m_tilerProgramSwizzleAA.clear(); m_canvasLayerProgram.clear(); m_pluginLayerProgram.clear(); m_pluginLayerProgramFlip.clear(); m_renderSurfaceMaskProgram.clear(); m_renderSurfaceMaskProgramAA.clear(); m_renderSurfaceProgram.clear(); m_renderSurfaceProgramAA.clear(); m_videoLayerRGBAProgram.clear(); m_videoLayerYUVProgram.clear(); if (m_offscreenFramebufferId) GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId)); releaseRenderSurfaceTextures(); }
void CCCanvasLayerImpl::draw(const IntRect&) { ASSERT(layerRenderer()); const CCCanvasLayerImpl::Program* program = layerRenderer()->canvasLayerProgram(); ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRenderer()->context(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA; GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); layerRenderer()->useShader(program->program()); GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), program->vertexShader().matrixLocation(), program->fragmentShader().alphaLocation()); }
void VideoLayerChromium::drawRGBA(const SharedValues* sv) { GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane])); layerRenderer()->useShader(sv->rgbaShaderProgram()); unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width(); unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width(); float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; GLC(context, context->uniform1f(sv->rgbaWidthScaleFactorLocation(), widthScaleFactor)); GLC(context, context->uniform1i(sv->rgbaTextureLocation(), 0)); drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), sv->rgbaShaderMatrixLocation(), sv->rgbaAlphaLocation()); }
void Canvas2DLayerChromium::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater) { if (!m_backTextureId || !m_frontTexture || !m_frontTexture->isValid(m_size, GraphicsContext3D::RGBA)) return; m_frontTexture->allocate(updater.allocator()); updater.copier()->copyTexture(context, m_backTextureId, m_frontTexture->textureId(), m_size); GLC(context, context->flush()); }
unsigned ProgramBindingBase::loadShader(GraphicsContext3D* context, unsigned type, const String& shaderSource) { unsigned shader = context->createShader(type); if (!shader) return 0; String sourceString(shaderSource); GLC(context, context->shaderSource(shader, sourceString)); GLC(context, context->compileShader(shader)); #ifndef NDEBUG int compiled = 0; GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled)); if (!compiled) { GLC(context, context->deleteShader(shader)); return 0; } #endif return shader; }