summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp')
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp225
1 files changed, 192 insertions, 33 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index a9f3d4665..acacc353b 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -46,6 +46,8 @@
#include "PlatformColor.h"
#include "PlatformContextSkia.h"
#include "RenderSurfaceChromium.h"
+#include "SharedGraphicsContext3D.h"
+#include "SkBitmap.h"
#include "TextureCopier.h"
#include "TextureManager.h"
#include "ThrottledTextureUploader.h"
@@ -56,11 +58,13 @@
#include "cc/CCDebugBorderDrawQuad.h"
#include "cc/CCIOSurfaceDrawQuad.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCLayerQuad.h"
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCMathUtil.h"
#include "cc/CCProxy.h"
#include "cc/CCRenderPass.h"
#include "cc/CCRenderSurfaceDrawQuad.h"
+#include "cc/CCRenderSurfaceFilters.h"
#include "cc/CCSolidColorDrawQuad.h"
#include "cc/CCTextureDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
@@ -70,16 +74,17 @@
#include <wtf/MainThread.h>
using namespace std;
+using WebKit::WebTransformationMatrix;
namespace WebCore {
namespace {
-static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
+static WebTransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
{
float deltaX = right - left;
float deltaY = top - bottom;
- TransformationMatrix ortho;
+ WebTransformationMatrix ortho;
if (!deltaX || !deltaY)
return ortho;
ortho.setM11(2.0f / deltaX);
@@ -94,9 +99,9 @@ static TransformationMatrix orthoMatrix(float left, float right, float bottom, f
return ortho;
}
-static TransformationMatrix screenMatrix(int x, int y, int width, int height)
+static WebTransformationMatrix screenMatrix(int x, int y, int width, int height)
{
- TransformationMatrix screen;
+ WebTransformationMatrix screen;
// Map to viewport.
screen.translate3d(x, y, 0);
@@ -522,7 +527,7 @@ void LayerRendererChromium::drawCheckerboardQuad(const CCCheckerboardDrawQuad* q
GLC(context(), context()->useProgram(program->program()));
IntRect tileRect = quad->quadRect();
- TransformationMatrix tileTransform = quad->quadTransform();
+ WebTransformationMatrix tileTransform = quad->quadTransform();
tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
float texOffsetX = tileRect.x();
@@ -551,7 +556,7 @@ void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua
GLC(context(), context()->useProgram(program->program()));
const IntRect& layerRect = quad->quadRect();
- TransformationMatrix renderMatrix = quad->quadTransform();
+ WebTransformationMatrix renderMatrix = quad->quadTransform();
renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y());
renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height());
LayerRendererChromium::toGLMatrix(&glMatrix[0], projectionMatrix() * renderMatrix);
@@ -568,7 +573,21 @@ void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua
GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
}
-void LayerRendererChromium::drawBackgroundFilters(const CCRenderSurfaceDrawQuad* quad)
+static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const WebKit::WebFilterOperations& filters, ManagedTexture* sourceTexture)
+{
+ if (filters.isEmpty())
+ return SkBitmap();
+
+ RefPtr<GraphicsContext3D> filterContext = CCProxy::hasImplThread() ? SharedGraphicsContext3D::getForImplThread() : SharedGraphicsContext3D::get();
+ if (!filterContext)
+ return SkBitmap();
+
+ layerRenderer->context()->flush();
+
+ return CCRenderSurfaceFilters::apply(filters, sourceTexture->textureId(), sourceTexture->size(), filterContext.get());
+}
+
+void LayerRendererChromium::drawBackgroundFilters(const CCRenderSurfaceDrawQuad* quad, const WebTransformationMatrix& contentsDeviceTransform)
{
// This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background.
// The algorithm works as follows:
@@ -585,7 +604,7 @@ void LayerRendererChromium::drawBackgroundFilters(const CCRenderSurfaceDrawQuad*
// Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
CCRenderSurface* drawingSurface = quad->layer()->renderSurface();
- if (drawingSurface->backgroundFilters().isEmpty())
+ if (quad->backgroundFilters().isEmpty())
return;
// FIXME: We only allow background filters on the root render surface because other surfaces may contain
@@ -593,17 +612,21 @@ void LayerRendererChromium::drawBackgroundFilters(const CCRenderSurfaceDrawQuad*
if (!isCurrentRenderSurface(m_defaultRenderSurface))
return;
- const TransformationMatrix& surfaceDrawTransform = quad->isReplica() ? drawingSurface->replicaDrawTransform() : drawingSurface->drawTransform();
-
// FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused).
- IntRect deviceRect = drawingSurface->readbackDeviceContentRect(this, surfaceDrawTransform);
+ IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().boundingBox()));
+
+ int top, right, bottom, left;
+ quad->backgroundFilters().getOutsets(top, right, bottom, left);
+ deviceRect.move(-left, -top);
+ deviceRect.expand(left + right, top + bottom);
+
deviceRect.intersect(m_currentRenderSurface->contentRect());
OwnPtr<ManagedTexture> deviceBackgroundTexture = ManagedTexture::create(m_renderSurfaceTextureManager.get());
if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
return;
- SkBitmap filteredDeviceBackground = drawingSurface->applyFilters(this, drawingSurface->backgroundFilters(), deviceBackgroundTexture.get());
+ SkBitmap filteredDeviceBackground = applyFilters(this, quad->backgroundFilters(), deviceBackgroundTexture.get());
if (!filteredDeviceBackground.getTexture())
return;
@@ -613,29 +636,144 @@ void LayerRendererChromium::drawBackgroundFilters(const CCRenderSurfaceDrawQuad*
if (!drawingSurface->prepareBackgroundTexture(this))
return;
- // This must be computed before switching the target render surface to the background texture.
- TransformationMatrix contentsDeviceTransform = drawingSurface->computeDeviceTransform(this, surfaceDrawTransform);
-
CCRenderSurface* targetRenderSurface = m_currentRenderSurface;
- if (useManagedTexture(drawingSurface->backgroundTexture(), drawingSurface->contentRect())) {
- drawingSurface->copyDeviceToBackgroundTexture(this, filteredDeviceBackgroundTextureId, deviceRect, contentsDeviceTransform);
+ if (useManagedTexture(drawingSurface->backgroundTexture(), quad->quadRect())) {
+ // Copy the readback pixels from device to the background texture for the surface.
+ WebTransformationMatrix deviceToSurfaceTransform;
+ deviceToSurfaceTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0);
+ deviceToSurfaceTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1);
+ deviceToSurfaceTransform.multiply(contentsDeviceTransform.inverse());
+ deviceToSurfaceTransform.translate(deviceRect.width() / 2.0, deviceRect.height() / 2.0);
+ deviceToSurfaceTransform.translate(deviceRect.x(), deviceRect.y());
+
+ copyTextureToFramebuffer(filteredDeviceBackgroundTextureId, deviceRect.size(), deviceToSurfaceTransform);
+
useRenderSurface(targetRenderSurface);
}
}
void LayerRendererChromium::drawRenderSurfaceQuad(const CCRenderSurfaceDrawQuad* quad)
{
- CCLayerImpl* layer = quad->layer();
+ // The replica is always drawn first, so free after drawing the contents.
+ bool shouldReleaseTextures = !quad->isReplica();
- drawBackgroundFilters(quad);
+ CCRenderSurface* drawingSurface = quad->layer()->renderSurface();
- layer->renderSurface()->setScissorRect(this, quad->surfaceDamageRect());
- if (quad->isReplica())
- layer->renderSurface()->drawReplica(this);
- else
- layer->renderSurface()->drawContents(this);
- layer->renderSurface()->releaseBackgroundTexture();
- layer->renderSurface()->releaseContentsTexture();
+ WebTransformationMatrix renderTransform = quad->layerTransform();
+ // Apply a scaling factor to size the quad from 1x1 to its intended size.
+ renderTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1);
+ WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(windowMatrix() * projectionMatrix() * renderTransform).to2dTransform();
+
+ // Can only draw surface if device matrix is invertible.
+ if (!contentsDeviceTransform.isInvertible() || !drawingSurface->hasValidContentsTexture()) {
+ if (shouldReleaseTextures) {
+ drawingSurface->releaseBackgroundTexture();
+ drawingSurface->releaseContentsTexture();
+ }
+ return;
+ }
+
+ drawBackgroundFilters(quad, contentsDeviceTransform);
+
+ // FIXME: Remove this call when the quad's scissorRect() is set correctly.
+ drawingSurface->setScissorRect(this, quad->surfaceDamageRect());
+
+ // FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
+ // Apply filters to the contents texture.
+ SkBitmap filterBitmap = applyFilters(this, quad->filters(), drawingSurface->contentsTexture());
+ int contentsTextureId = drawingSurface->contentsTexture()->textureId();
+ if (filterBitmap.getTexture()) {
+ GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
+ contentsTextureId = texture->getTextureHandle();
+ }
+
+ // Draw the background texture if there is one.
+ if (drawingSurface->hasValidBackgroundTexture())
+ copyTextureToFramebuffer(drawingSurface->backgroundTexture()->textureId(), quad->quadRect().size(), quad->layerTransform());
+
+ FloatQuad deviceQuad = contentsDeviceTransform.mapQuad(sharedGeometryQuad());
+ CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox()));
+ CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad);
+
+ // Use anti-aliasing programs only when necessary.
+ bool useAA = (!deviceQuad.isRectilinear() || !deviceQuad.boundingBox().isExpressibleAsIntRect());
+ if (useAA) {
+ deviceLayerBounds.inflateAntiAliasingDistance();
+ deviceLayerEdges.inflateAntiAliasingDistance();
+ }
+
+ bool useMask = quad->maskTextureId();
+
+ // FIXME: use the backgroundTexture and blend the background in with this draw instead of having a separate copy of the background texture.
+
+ GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+ context()->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId);
+
+ int shaderQuadLocation = -1;
+ int shaderEdgeLocation = -1;
+ int shaderMaskSamplerLocation = -1;
+ int shaderMatrixLocation = -1;
+ int shaderAlphaLocation = -1;
+ if (useAA && useMask) {
+ const RenderSurfaceMaskProgramAA* program = renderSurfaceMaskProgramAA();
+ GLC(context(), context()->useProgram(program->program()));
+ GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+ shaderQuadLocation = program->vertexShader().pointLocation();
+ shaderEdgeLocation = program->fragmentShader().edgeLocation();
+ shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
+ shaderMatrixLocation = program->vertexShader().matrixLocation();
+ shaderAlphaLocation = program->fragmentShader().alphaLocation();
+ } else if (!useAA && useMask) {
+ const RenderSurfaceMaskProgram* program = renderSurfaceMaskProgram();
+ GLC(context(), context()->useProgram(program->program()));
+ GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+ shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
+ shaderMatrixLocation = program->vertexShader().matrixLocation();
+ shaderAlphaLocation = program->fragmentShader().alphaLocation();
+ } else if (useAA && !useMask) {
+ const RenderSurfaceProgramAA* program = renderSurfaceProgramAA();
+ GLC(context(), context()->useProgram(program->program()));
+ GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+ shaderQuadLocation = program->vertexShader().pointLocation();
+ shaderEdgeLocation = program->fragmentShader().edgeLocation();
+ shaderMatrixLocation = program->vertexShader().matrixLocation();
+ shaderAlphaLocation = program->fragmentShader().alphaLocation();
+ } else {
+ const RenderSurfaceProgram* program = renderSurfaceProgram();
+ GLC(context(), context()->useProgram(program->program()));
+ GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+ shaderMatrixLocation = program->vertexShader().matrixLocation();
+ shaderAlphaLocation = program->fragmentShader().alphaLocation();
+ }
+
+ if (shaderMaskSamplerLocation != -1) {
+ GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
+ GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1));
+ context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->maskTextureId());
+ GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+ }
+
+ if (shaderEdgeLocation != -1) {
+ float edge[24];
+ deviceLayerEdges.toFloatArray(edge);
+ deviceLayerBounds.toFloatArray(&edge[12]);
+ GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge));
+ }
+
+ // Map device space quad to surface space.
+ FloatQuad surfaceQuad = contentsDeviceTransform.inverse().mapQuad(deviceLayerEdges.floatQuad());
+
+ drawTexturedQuad(quad->layerTransform(), quad->quadRect().width(), quad->quadRect().height(), quad->opacity(), surfaceQuad,
+ shaderMatrixLocation, shaderAlphaLocation, shaderQuadLocation);
+
+ if (shouldReleaseTextures) {
+ drawingSurface->releaseBackgroundTexture();
+ drawingSurface->releaseContentsTexture();
+ }
}
void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad)
@@ -645,7 +783,7 @@ void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad)
IntRect tileRect = quad->quadRect();
- TransformationMatrix tileTransform = quad->quadTransform();
+ WebTransformationMatrix tileTransform = quad->quadTransform();
tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
const Color& color = quad->color();
@@ -721,7 +859,7 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
FloatQuad localQuad;
- TransformationMatrix deviceTransform = TransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
+ WebTransformationMatrix deviceTransform = WebTransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
if (!deviceTransform.isInvertible())
return;
@@ -810,7 +948,7 @@ void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
// Map quad to layer space.
- TransformationMatrix inverseDeviceTransform = deviceTransform.inverse();
+ WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse();
localQuad = inverseDeviceTransform.mapQuad(deviceQuad.floatQuad());
} else {
// Move fragment shader transform to vertex shader. We can do this while
@@ -1083,7 +1221,7 @@ void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const
GLC(m_context, m_context->useProgram(program->program()));
GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocation(), 0));
- TransformationMatrix matrix;
+ WebTransformationMatrix matrix;
matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
1, sharedGeometryQuad(), program->vertexShader().matrixLocation(),
@@ -1096,6 +1234,8 @@ void LayerRendererChromium::finishDrawingFrame()
GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
+ m_renderSurfaceTextureManager->unprotectAllTextures();
+
size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
size_t reclaimLimit = TextureManager::reclaimLimitBytes(viewportSize());
size_t preferredLimit = reclaimLimit > contentsMemoryUseBytes ? reclaimLimit - contentsMemoryUseBytes : 0;
@@ -1104,7 +1244,7 @@ void LayerRendererChromium::finishDrawingFrame()
m_renderSurfaceTextureManager->deleteEvictedTextures(m_renderSurfaceTextureAllocator.get());
}
-void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
+void LayerRendererChromium::toGLMatrix(float* flattened, const WebTransformationMatrix& m)
{
flattened[0] = m.m11();
flattened[1] = m.m12();
@@ -1124,13 +1264,13 @@ void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMat
flattened[15] = m.m44();
}
-void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMatrix,
+void LayerRendererChromium::drawTexturedQuad(const WebTransformationMatrix& drawMatrix,
float width, float height, float opacity, const FloatQuad& quad,
int matrixLocation, int alphaLocation, int quadLocation)
{
static float glMatrix[16];
- TransformationMatrix renderMatrix = drawMatrix;
+ WebTransformationMatrix renderMatrix = drawMatrix;
// Apply a scaling factor to size the quad from 1x1 to its intended size.
renderMatrix.scale3d(width, height, 1);
@@ -1159,6 +1299,25 @@ void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMat
GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
}
+void LayerRendererChromium::copyTextureToFramebuffer(int textureId, const IntSize& bounds, const WebTransformationMatrix& drawMatrix)
+{
+ const RenderSurfaceProgram* program = renderSurfaceProgram();
+
+ GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ 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(program->program()));
+ GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+ drawTexturedQuad(drawMatrix, bounds.width(), bounds.height(), 1, sharedGeometryQuad(),
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation(),
+ -1);
+}
+
void LayerRendererChromium::finish()
{
TRACE_EVENT("LayerRendererChromium::finish", this, 0);