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()); } }
void VideoLayerChromium::drawYUV(const SharedValues* sv) { GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane])); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane])); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane])); layerRenderer()->useShader(sv->yuvShaderProgram()); unsigned frameWidth = m_frameSizes[VideoFrameChromium::yPlane].width(); unsigned textureWidth = m_textureSizes[VideoFrameChromium::yPlane].width(); float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; GLC(context, context->uniform1f(sv->yuvWidthScaleFactorLocation(), widthScaleFactor)); GLC(context, context->uniform1i(sv->yTextureLocation(), 1)); GLC(context, context->uniform1i(sv->uTextureLocation(), 2)); GLC(context, context->uniform1i(sv->vTextureLocation(), 3)); GLC(context, context->uniformMatrix3fv(sv->ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), bounds().width(), bounds().height(), drawOpacity(), sv->yuvShaderMatrixLocation(), sv->yuvAlphaLocation()); // Reset active texture back to texture 0. GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); }
TransformationMatrix CCSolidColorLayerImpl::quadTransform() const { TransformationMatrix solidColorTransform = drawTransform(); solidColorTransform.translate(-bounds().width() / 2.0, -bounds().height() / 2.0); return solidColorTransform; }
PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const { IntRect layerClipRect; if (usesLayerClipping()) layerClipRect = clipRect(); return CCSharedQuadState::create(quadTransform(), drawTransform(), visibleLayerRect(), layerClipRect, drawOpacity(), opaque()); }
void ContentLayerChromium::calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const { // For the given layer size and content rect, calculate: // 1) The minimal texture space rectangle to be uploaded, returned in dirtyRect. // 2) The rectangle to draw this texture in relative to the target render surface, returned in drawRect. ASSERT(m_targetRenderSurface); const IntRect clipRect = m_targetRenderSurface->contentRect(); TransformationMatrix layerOriginTransform = drawTransform(); layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0); // For now we apply the large layer treatment only for layers that are either untransformed // or are purely translated. Their matrix is expected to be invertible. ASSERT(layerOriginTransform.isInvertible()); TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse(); IntRect clipRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect); clipRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height())); dirtyRect = clipRectInLayerCoords; // Map back to the target surface coordinate system. drawRect = layerOriginTransform.mapRect(dirtyRect); }
const IntRect CCLayerImpl::getDrawRect() const { // Form the matrix used by the shader to map the corners of the layer's // bounds into the view space. FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height()); IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect)); return mappedRect; }
TransformationMatrix CCLayerImpl::quadTransform() const { TransformationMatrix quadTransformation = drawTransform(); float offsetX = -0.5 * bounds().width(); float offsetY = -0.5 * bounds().height(); quadTransformation.translate(offsetX, offsetY); return quadTransformation; }
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()); }
TransformationMatrix TiledLayerChromium::tilingTransform() const { TransformationMatrix transform = drawTransform(); if (contentBounds().isEmpty()) return transform; transform.scaleNonUniform(bounds().width() / static_cast<double>(contentBounds().width()), bounds().height() / static_cast<double>(contentBounds().height())); // Tiler draws with a different origin from other layers. transform.translate(-contentBounds().width() / 2.0, -contentBounds().height() / 2.0); transform.translate(-scrollPosition().x(), -scrollPosition().y()); return transform; }
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()); }
bool FixedBackgroundImageLayerAndroid::drawGL(bool layerTilesDisabled) { if (layerTilesDisabled) return false; if (!m_imageCRC) return false; ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); if (!imageTexture) { ImagesManager::instance()->releaseImage(m_imageCRC); return false; } // We have a fixed background image, let's draw it if (m_fixedPosition && m_fixedPosition->isBackgroundImagePositioning()) { BackgroundImagePositioning* position = static_cast<BackgroundImagePositioning*>(m_fixedPosition); IntPoint repeatTimes(position->nbRepeatX(), position->nbRepeatY()); FloatPoint startPoint(position->offsetX() * getWidth(), position->offsetY() * getHeight()); FloatPoint origin; origin = drawTransform()->mapPoint(origin); Color backgroundColor = Color((int)SkColorGetR(m_backgroundColor), (int)SkColorGetG(m_backgroundColor), (int)SkColorGetB(m_backgroundColor), (int)SkColorGetA(m_backgroundColor)); bool drawSimpleQuadSuccess = drawSimpleQuad(imageTexture, position, repeatTimes, startPoint, origin, backgroundColor); if (!drawSimpleQuadSuccess) { drawRepeatedGrid(imageTexture, position, repeatTimes, startPoint, origin, backgroundColor); } } else imageTexture->drawGL(this, getOpacity()); ImagesManager::instance()->releaseImage(m_imageCRC); return false; }
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()); }
bool Surface::drawGL(bool layerTilesDisabled) { bool tilesDisabled = layerTilesDisabled && !isBase(); // SAMSUNG CHANGE ++ : google handwriting 'g' icon display issue, Youtube.com 356x2 height line display issue // This patch should be applied with DEV CL 56175 // WAS:if (singleLayer() && !getFirstLayer()->visible()) if (singleLayer() && (!getFirstLayer()->visible() || getFirstLayer()->drawOpacity() <= 0.0f)) return false; //SAMSUNG CHANGE -- if (!isBase()) { FloatRect drawClip = getFirstLayer()->drawClip(); if (!singleLayer()) { for (unsigned int i = 1; i < m_layers.size(); i++) drawClip.unite(m_layers[i]->drawClip()); } FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip); TilesManager::instance()->shader()->clip(clippingRect); } bool askRedraw = false; if (m_surfaceBacking && !tilesDisabled) { ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking, getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId()); bool force3dContentVisible = true; IntRect drawArea = visibleContentArea(force3dContentVisible); m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(), useAggressiveRendering(), background()); } // draw member layers (draws image textures, glextras) for (unsigned int i = 0; i < m_layers.size(); i++) { if (m_layers[i]->drawGL(tilesDisabled)) { m_layers[i]->addDirtyArea(); askRedraw = true; } } return askRedraw; }
void CCVideoLayerImpl::drawNativeTexture(LayerRendererChromium* layerRenderer) const { const NativeTextureProgram* program = layerRenderer->videoLayerNativeTextureProgram(); ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRenderer->context(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_nativeTextureId)); GLC(context, context->useProgram(program->program())); float widthScaleFactor = static_cast<float>(m_nativeTextureVisibleSize.width()) / m_nativeTextureSize.width(); GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(), program->vertexShader().matrixLocation(), program->fragmentShader().alphaLocation(), -1); }
void CCVideoLayerImpl::drawYUV(LayerRendererChromium* layerRenderer) const { const YUVProgram* program = layerRenderer->videoLayerYUVProgram(); ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRenderer->context(); CCVideoLayerImpl::Texture yTexture = m_textures[VideoFrameChromium::yPlane]; CCVideoLayerImpl::Texture uTexture = m_textures[VideoFrameChromium::uPlane]; CCVideoLayerImpl::Texture vTexture = m_textures[VideoFrameChromium::vPlane]; GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id)); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id)); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id)); GLC(context, context->useProgram(program->program())); float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width(); // Arbitrarily take the u sizes because u and v dimensions are identical. float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width(); GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1)); layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), FloatQuad(), program->vertexShader().matrixLocation(), program->fragmentShader().alphaLocation(), -1); // Reset active texture back to texture 0. GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); }
void CCPluginLayerImpl::draw() { ASSERT(layerRenderer()); const CCPluginLayerImpl::Program* program = layerRenderer()->pluginLayerProgram(); ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRenderer()->context(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); // FIXME: setting the texture parameters every time is redundant. Move this code somewhere // where it will only happen once per texture. GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); 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()); }
bool Surface::drawGL(bool layerTilesDisabled) { bool tilesDisabled = layerTilesDisabled && !isBase(); if (singleLayer() && !getFirstLayer()->visible()) return false; if (!isBase()) { FloatRect drawClip = getFirstLayer()->drawClip(); if (!singleLayer()) { for (unsigned int i = 1; i < m_layers.size(); i++) drawClip.unite(m_layers[i]->drawClip()); } FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip); TilesManager::instance()->shader()->clip(clippingRect); } bool askRedraw = false; if (m_surfaceBacking && !tilesDisabled) { ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking, getFirstLayer()->subclassName(), getFirstLayer()->uniqueId()); bool force3dContentVisible = true; IntRect drawArea = visibleContentArea(force3dContentVisible); m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(), useAggressiveRendering(), background()); } // draw member layers (draws image textures, glextras) for (unsigned int i = 0; i < m_layers.size(); i++) { if (m_layers[i]->drawGL(tilesDisabled)) { m_layers[i]->addDirtyArea(); askRedraw = true; } } return askRedraw; }
PassOwnPtr<CCSharedQuadState> CCRenderSurface::createSharedQuadState() const { bool isOpaque = false; return CCSharedQuadState::create(originTransform(), drawTransform(), contentRect(), clipRect(), drawOpacity(), isOpaque); }
void CCDelegatedRendererLayerImpl::appendRenderPassQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData, CCRenderPass* delegatedRenderPass) const { const CCSharedQuadState* currentSharedQuadState = 0; CCSharedQuadState* copiedSharedQuadState = 0; for (size_t i = 0; i < delegatedRenderPass->quadList().size(); ++i) { CCDrawQuad* quad = delegatedRenderPass->quadList()[i]; if (quad->sharedQuadState() != currentSharedQuadState) { currentSharedQuadState = quad->sharedQuadState(); copiedSharedQuadState = quadSink.useSharedQuadState(currentSharedQuadState->copy()); } ASSERT(copiedSharedQuadState); bool targetIsFromDelegatedRendererLayer = appendQuadsData.renderPassId.layerId == id(); if (!targetIsFromDelegatedRendererLayer) { // Should be the root render pass. ASSERT(delegatedRenderPass == m_renderPassesInDrawOrder.last()); // This layer must be drawing to a renderTarget other than itself. ASSERT(renderTarget() != this); copiedSharedQuadState->quadTransform = copiedSharedQuadState->quadTransform * drawTransform(); copiedSharedQuadState->opacity *= drawOpacity(); } scoped_ptr<CCDrawQuad> copyQuad; if (quad->material() != CCDrawQuad::RenderPass) copyQuad = quad->copy(copiedSharedQuadState); else { CCRenderPass::Id contributingDelegatedRenderPassId = CCRenderPassDrawQuad::materialCast(quad)->renderPassId(); CCRenderPass::Id contributingRenderPassId = convertDelegatedRenderPassId(contributingDelegatedRenderPassId); ASSERT(contributingRenderPassId != appendQuadsData.renderPassId); copyQuad = CCRenderPassDrawQuad::materialCast(quad)->copy(copiedSharedQuadState, contributingRenderPassId).PassAs<CCDrawQuad>(); } ASSERT(copyQuad.get()); quadSink.append(copyQuad.Pass(), appendQuadsData); } }
void ContentLayerChromium::updateContents() { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); if (!backing || backing->paintingGoesToWindow()) return; ASSERT(drawsContent()); ASSERT(layerRenderer()); void* pixels = 0; IntRect dirtyRect; IntRect updateRect; IntSize requiredTextureSize; IntSize bitmapSize; // FIXME: Remove this test when tiled layers are implemented. if (requiresClippedUpdateRect()) { // A layer with 3D transforms could require an arbitrarily large number // of texels to be repainted, so ignore these layers until tiling is // implemented. if (!drawTransform().isIdentityOrTranslation()) { m_skipsDraw = true; return; } calculateClippedUpdateRect(dirtyRect, m_largeLayerDrawRect); if (!layerRenderer()->checkTextureSize(m_largeLayerDrawRect.size())) { m_skipsDraw = true; return; } // If the portion of the large layer that's visible hasn't changed // then we don't need to update it, _unless_ its contents have changed // in which case we only update the dirty bits. if (m_largeLayerDirtyRect == dirtyRect) { if (!m_dirtyRect.intersects(dirtyRect)) return; dirtyRect.intersect(IntRect(m_dirtyRect)); updateRect = dirtyRect; requiredTextureSize = m_largeLayerDirtyRect.size(); } else { m_largeLayerDirtyRect = dirtyRect; requiredTextureSize = dirtyRect.size(); updateRect = IntRect(IntPoint(0, 0), dirtyRect.size()); } } else { dirtyRect = IntRect(m_dirtyRect); IntRect boundsRect(IntPoint(0, 0), m_bounds); requiredTextureSize = m_bounds; // If the texture needs to be reallocated then we must redraw the entire // contents of the layer. if (requiredTextureSize != m_allocatedTextureSize) dirtyRect = boundsRect; else { // Clip the dirtyRect to the size of the layer to avoid drawing // outside the bounds of the backing texture. dirtyRect.intersect(boundsRect); } updateRect = dirtyRect; } if (dirtyRect.isEmpty()) return; #if PLATFORM(SKIA) const SkBitmap* skiaBitmap = 0; OwnPtr<skia::PlatformCanvas> canvas; OwnPtr<PlatformContextSkia> skiaContext; OwnPtr<GraphicsContext> graphicsContext; canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); skiaContext.set(new PlatformContextSkia(canvas.get())); // This is needed to get text to show up correctly. // FIXME: Does this take us down a very slow text rendering path? skiaContext->setDrawingToImageBuffer(true); graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); // Bring the canvas into the coordinate system of the paint rect. canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); skiaBitmap = &bitmap; ASSERT(skiaBitmap); SkAutoLockPixels lock(*skiaBitmap); SkBitmap::Config skiaConfig = skiaBitmap->config(); // FIXME: do we need to support more image configurations? if (skiaConfig == SkBitmap::kARGB_8888_Config) { pixels = skiaBitmap->getPixels(); bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); } #elif PLATFORM(CG) Vector<uint8_t> tempVector; int rowBytes = 4 * dirtyRect.width(); tempVector.resize(rowBytes * dirtyRect.height()); memset(tempVector.data(), 0, tempVector.size()); RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height()); CGContextScaleCTM(contextCG.get(), 1, -1); GraphicsContext graphicsContext(contextCG.get()); // Translate the graphics context into the coordinate system of the dirty rect. graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y()); m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect); pixels = tempVector.data(); bitmapSize = dirtyRect.size(); #else #error "Need to implement for your platform." #endif unsigned textureId = m_contentsTexture; if (!textureId) textureId = layerRenderer()->createLayerTexture(); if (pixels) updateTextureRect(pixels, bitmapSize, requiredTextureSize, updateRect, textureId); }
// Return true when fast draw succeeds. // For the repeated image content, we just need to draw a single quad and use // the GL shader to repeat. bool FixedBackgroundImageLayerAndroid::drawSimpleQuad(ImageTexture* imageTexture, BackgroundImagePositioning* position, const IntPoint& repeatTimes, const FloatPoint& startPoint, const FloatPoint& origin, const Color& backgroundColor) { // The limitation for current implementation is that we can only speed up // single tile size image. // TODO: add the fast path to imageTexture which contains >1 tiles. GLuint imageTextureId = imageTexture->getImageTextureId(); if (!imageTextureId) return false; int nbX = repeatTimes.x(); int nbY = repeatTimes.y(); float startX = startPoint.x(); float startY = startPoint.y(); bool repeatX = position->repeatX(); bool repeatY = position->repeatY(); // Draw the entire background when repeat only in one direction or no repeat. if (!repeatX || !repeatY) { SkRect backgroundRect; backgroundRect.fLeft = origin.x() - startX; backgroundRect.fTop = origin.y() - startY; backgroundRect.fRight = backgroundRect.fLeft + getWidth() * nbX; backgroundRect.fBottom = backgroundRect.fTop + getHeight() * nbY; PureColorQuadData backgroundData(backgroundColor, BaseQuad, 0, &backgroundRect, 1.0, true); TilesManager::instance()->shader()->drawQuad(&backgroundData); } // Now draw the repeated images. // We set the quad size as the image size, then imageRepeatRanges will // control how many times the image will be repeated by expanding the // quad and texture coordinates. // The image size can be smaller than a tile, so repeatScale will passed // into the shader to scale the texture coordinates. SkRect imageRect = SkRect::MakeXYWH(0, 0, getWidth(), getHeight()); FloatRect imageRepeatRanges(0, 0, repeatX ? nbX : 1, repeatY ? nbY : 1); FloatSize repeatScale(float(getWidth()) / TilesManager::tileWidth(), float(getHeight()) / TilesManager::tileHeight()); ALOGV("repeatedQuadData: startX %f, startY %f , getWidth() %f, getHeight() %f," " nbX %d, nbY %d, repeatImageTimesX, repeatImageTimesY %d %d" " repeatScale width %f, height %f, origin x %f y %f", startX , startY , getWidth(), getHeight(), nbX , nbY, imageRepeatRanges.width(), imageRepeatRanges.height(), repeatScale.width(), repeatScale.height(), origin.x(), origin.y()); // Adding startX and startY into the transform can handle the fixed right / // fixed bottom case. TransformationMatrix matrix = *drawTransform(); matrix.translate(repeatX ? -startX : 0, repeatY ? -startY : 0); TextureQuadData repeatedQuadData(imageTextureId, GL_TEXTURE_2D, GL_LINEAR, LayerQuad, &matrix, &imageRect, getOpacity(), true, imageRepeatRanges, repeatScale); TilesManager::instance()->shader()->drawQuad(&repeatedQuadData); return true; }
PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const { return CCSharedQuadState::create(quadTransform(), drawTransform(), visibleLayerRect(), m_scissorRect, drawOpacity(), opaque()); }
void CCTiledLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) { const IntRect& contentRect = visibleContentRect(); if (!m_tiler || m_tiler->hasEmptyBounds() || contentRect.isEmpty()) return; CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); int left, top, right, bottom; m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom); if (hasDebugBorders()) { for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { DrawableTile* tile = tileAt(i, j); IntRect tileRect = m_tiler->tileBounds(i, j); SkColor borderColor; if (m_skipsDraw || !tile || !tile->resourceId()) borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue); else borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); quadSink.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth).PassAs<CCDrawQuad>(), appendQuadsData); } } } if (m_skipsDraw) return; for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { DrawableTile* tile = tileAt(i, j); IntRect tileRect = m_tiler->tileBounds(i, j); IntRect displayRect = tileRect; tileRect.intersect(contentRect); // Skip empty tiles. if (tileRect.isEmpty()) continue; if (!tile || !tile->resourceId()) { if (drawCheckerboardForMissingTiles()) { SkColor defaultColor = SkColorSetRGB(defaultCheckerboardColorRed, defaultCheckerboardColorGreen, defaultCheckerboardColorBlue); SkColor evictedColor = SkColorSetRGB(debugTileEvictedCheckerboardColorRed, debugTileEvictedCheckerboardColorGreen, debugTileEvictedCheckerboardColorBlue); SkColor invalidatedColor = SkColorSetRGB(debugTileInvalidatedCheckerboardColorRed, debugTileEvictedCheckerboardColorGreen, debugTileEvictedCheckerboardColorBlue); SkColor checkerColor; if (hasDebugBorders()) checkerColor = tile ? invalidatedColor : evictedColor; else checkerColor = defaultColor; appendQuadsData.hadMissingTiles |= quadSink.append(CCCheckerboardDrawQuad::create(sharedQuadState, tileRect, checkerColor).PassAs<CCDrawQuad>(), appendQuadsData); } else appendQuadsData.hadMissingTiles |= quadSink.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()).PassAs<CCDrawQuad>(), appendQuadsData); continue; } IntRect tileOpaqueRect = tile->opaqueRect(); tileOpaqueRect.intersect(contentRect); // Keep track of how the top left has moved, so the texture can be // offset the same amount. IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner(); IntPoint textureOffset = m_tiler->textureOffset(i, j) + displayOffset; float tileWidth = static_cast<float>(m_tiler->tileSize().width()); float tileHeight = static_cast<float>(m_tiler->tileSize().height()); IntSize textureSize(tileWidth, tileHeight); bool clipped = false; FloatQuad visibleContentInTargetQuad = CCMathUtil::mapQuad(drawTransform(), FloatQuad(visibleContentRect()), clipped); bool isAxisAlignedInTarget = !clipped && visibleContentInTargetQuad.isRectilinear(); bool useAA = m_tiler->hasBorderTexels() && !isAxisAlignedInTarget; bool leftEdgeAA = !i && useAA; bool topEdgeAA = !j && useAA; bool rightEdgeAA = i == m_tiler->numTilesX() - 1 && useAA; bool bottomEdgeAA = j == m_tiler->numTilesY() - 1 && useAA; const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST; quadSink.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tileOpaqueRect, tile->resourceId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA).PassAs<CCDrawQuad>(), appendQuadsData); } } }
void CCPluginLayerImpl::draw(LayerRendererChromium* layerRenderer) { ASSERT(CCProxy::isImplThread()); if (m_ioSurfaceChanged) { GraphicsContext3D* context = layerRenderer->context(); Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions()); ASSERT(extensions->supports("GL_CHROMIUM_iosurface")); ASSERT(extensions->supports("GL_ARB_texture_rectangle")); if (!m_ioSurfaceTextureId) m_ioSurfaceTextureId = context->createTexture(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId)); GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); extensions->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceWidth, m_ioSurfaceHeight, m_ioSurfaceId, 0); // Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to // the last good IOSurface if the new one is already closed. This is only a possibility // during live resizing of plugins. However, it seems that this is not sufficient to // completely guard against garbage being drawn. If this is found to be a significant issue, // it may be necessary to explicitly tell the embedder when to free the surfaces it has // allocated. m_ioSurfaceChanged = false; } if (m_ioSurfaceTextureId) { TexTransformPluginProgramBinding binding; if (m_flipped) binding.set(layerRenderer->pluginLayerTexRectProgramFlip()); else binding.set(layerRenderer->pluginLayerTexRectProgram()); GraphicsContext3D* context = layerRenderer->context(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId)); GLC(context, context->useProgram(binding.programId)); GLC(context, context->uniform1i(binding.samplerLocation, 0)); // Note: this code path ignores m_uvRect. GLC(context, context->uniform4f(binding.texTransformLocation, 0, 0, m_ioSurfaceWidth, m_ioSurfaceHeight)); layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1); GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0)); } else { TexStretchPluginProgramBinding binding; if (m_flipped) binding.set(layerRenderer->pluginLayerProgramFlip()); else binding.set(layerRenderer->pluginLayerProgram()); GraphicsContext3D* context = layerRenderer->context(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); // FIXME: setting the texture parameters every time is redundant. Move this code somewhere // where it will only happen once per texture. GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); GLC(context, context->useProgram(binding.programId)); GLC(context, context->uniform1i(binding.samplerLocation, 0)); GLC(context, context->uniform2f(binding.offsetLocation, m_uvRect.x(), m_uvRect.y())); GLC(context, context->uniform2f(binding.scaleLocation, m_uvRect.width(), m_uvRect.height())); layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1); } }