158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com/* 258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * Copyright 2012 Google Inc. 358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * 458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * found in the LICENSE file. 658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com */ 758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com#include "GrSWMaskHelper.h" 95c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski 1058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com#include "GrDrawState.h" 119528bdb0dccee915505bcf99cb10659f85e2604brobertphillips@google.com#include "GrDrawTargetCaps.h" 1258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com#include "GrGpu.h" 1358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 145c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski#include "SkData.h" 155f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h" 1612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com 1758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com// TODO: try to remove this #include 1858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com#include "GrContext.h" 1958b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 2058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.comnamespace { 215c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski 2258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com/* 2358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * Convert a boolean operation into a transfer mode code 2458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com */ 2558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.comSkXfermode::Mode op_to_mode(SkRegion::Op op) { 2658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 2758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com static const SkXfermode::Mode modeMap[] = { 2858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkXfermode::kDstOut_Mode, // kDifference_Op 298d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com SkXfermode::kModulate_Mode, // kIntersect_Op 3058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkXfermode::kSrcOver_Mode, // kUnion_Op 3158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkXfermode::kXor_Mode, // kXOR_Op 3258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkXfermode::kClear_Mode, // kReverseDifference_Op 3358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkXfermode::kSrc_Mode, // kReplace_Op 3458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com }; 3558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 3658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com return modeMap[op]; 3758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 3858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 3925a67bcb7ac70d3077e91126c4b8924a53557a38krajcevskistatic inline GrPixelConfig fmt_to_config(SkTextureCompressor::Format fmt) { 4025a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski 4195b1b3d82d227141647777d83324aa570b530096krajcevski GrPixelConfig config; 4295b1b3d82d227141647777d83324aa570b530096krajcevski switch (fmt) { 4395b1b3d82d227141647777d83324aa570b530096krajcevski case SkTextureCompressor::kLATC_Format: 4495b1b3d82d227141647777d83324aa570b530096krajcevski config = kLATC_GrPixelConfig; 4595b1b3d82d227141647777d83324aa570b530096krajcevski break; 4695b1b3d82d227141647777d83324aa570b530096krajcevski 4795b1b3d82d227141647777d83324aa570b530096krajcevski case SkTextureCompressor::kR11_EAC_Format: 4895b1b3d82d227141647777d83324aa570b530096krajcevski config = kR11_EAC_GrPixelConfig; 4995b1b3d82d227141647777d83324aa570b530096krajcevski break; 5095b1b3d82d227141647777d83324aa570b530096krajcevski 5195b1b3d82d227141647777d83324aa570b530096krajcevski case SkTextureCompressor::kASTC_12x12_Format: 5295b1b3d82d227141647777d83324aa570b530096krajcevski config = kASTC_12x12_GrPixelConfig; 5395b1b3d82d227141647777d83324aa570b530096krajcevski break; 5495b1b3d82d227141647777d83324aa570b530096krajcevski 5595b1b3d82d227141647777d83324aa570b530096krajcevski case SkTextureCompressor::kETC1_Format: 5695b1b3d82d227141647777d83324aa570b530096krajcevski config = kETC1_GrPixelConfig; 5795b1b3d82d227141647777d83324aa570b530096krajcevski break; 5895b1b3d82d227141647777d83324aa570b530096krajcevski 5995b1b3d82d227141647777d83324aa570b530096krajcevski default: 6095b1b3d82d227141647777d83324aa570b530096krajcevski SkDEBUGFAIL("No GrPixelConfig for compression format!"); 6195b1b3d82d227141647777d83324aa570b530096krajcevski // Best guess 6295b1b3d82d227141647777d83324aa570b530096krajcevski config = kAlpha_8_GrPixelConfig; 6395b1b3d82d227141647777d83324aa570b530096krajcevski break; 6495b1b3d82d227141647777d83324aa570b530096krajcevski } 6595b1b3d82d227141647777d83324aa570b530096krajcevski 6695b1b3d82d227141647777d83324aa570b530096krajcevski return config; 6725a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski} 6825a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski 69b3abe90145b988883c9882de1ac42da963adbf67krajcevskistatic bool choose_compressed_fmt(const GrDrawTargetCaps* caps, 70b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkTextureCompressor::Format *fmt) { 71b3abe90145b988883c9882de1ac42da963adbf67krajcevski if (NULL == fmt) { 72b3abe90145b988883c9882de1ac42da963adbf67krajcevski return false; 73b3abe90145b988883c9882de1ac42da963adbf67krajcevski } 74b3abe90145b988883c9882de1ac42da963adbf67krajcevski 75b3abe90145b988883c9882de1ac42da963adbf67krajcevski // We can't use scratch textures without the ability to update 76b3abe90145b988883c9882de1ac42da963adbf67krajcevski // compressed textures... 77b3abe90145b988883c9882de1ac42da963adbf67krajcevski if (!(caps->compressedTexSubImageSupport())) { 78b3abe90145b988883c9882de1ac42da963adbf67krajcevski return false; 79b3abe90145b988883c9882de1ac42da963adbf67krajcevski } 80b3abe90145b988883c9882de1ac42da963adbf67krajcevski 81b3abe90145b988883c9882de1ac42da963adbf67krajcevski // Figure out what our preferred texture type is. If ASTC is available, that always 82b3abe90145b988883c9882de1ac42da963adbf67krajcevski // gives the biggest win. Otherwise, in terms of compression speed and accuracy, 83b3abe90145b988883c9882de1ac42da963adbf67krajcevski // LATC has a slight edge over R11 EAC. 84b3abe90145b988883c9882de1ac42da963adbf67krajcevski if (caps->isConfigTexturable(kASTC_12x12_GrPixelConfig)) { 85b3abe90145b988883c9882de1ac42da963adbf67krajcevski *fmt = SkTextureCompressor::kASTC_12x12_Format; 86b3abe90145b988883c9882de1ac42da963adbf67krajcevski return true; 87b3abe90145b988883c9882de1ac42da963adbf67krajcevski } else if (caps->isConfigTexturable(kLATC_GrPixelConfig)) { 88b3abe90145b988883c9882de1ac42da963adbf67krajcevski *fmt = SkTextureCompressor::kLATC_Format; 89b3abe90145b988883c9882de1ac42da963adbf67krajcevski return true; 90b3abe90145b988883c9882de1ac42da963adbf67krajcevski } else if (caps->isConfigTexturable(kR11_EAC_GrPixelConfig)) { 91b3abe90145b988883c9882de1ac42da963adbf67krajcevski *fmt = SkTextureCompressor::kR11_EAC_Format; 92b3abe90145b988883c9882de1ac42da963adbf67krajcevski return true; 93b3abe90145b988883c9882de1ac42da963adbf67krajcevski } 94b3abe90145b988883c9882de1ac42da963adbf67krajcevski 95b3abe90145b988883c9882de1ac42da963adbf67krajcevski return false; 96b3abe90145b988883c9882de1ac42da963adbf67krajcevski} 97b3abe90145b988883c9882de1ac42da963adbf67krajcevski 9858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 9958b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 10058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com/** 10158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * Draw a single rect element of the clip stack into the accumulation bitmap 10258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com */ 103fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgvoid GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op, 104366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com bool antiAlias, uint8_t alpha) { 10558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkPaint paint; 10658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 10758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); 10858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 10971614ac7c63fe60dfe971f861e2b2d6325dd0039krajcevski SkASSERT(kNone_CompressionMode == fCompressionMode); 11071614ac7c63fe60dfe971f861e2b2d6325dd0039krajcevski 11158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com paint.setXfermode(mode); 11258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com paint.setAntiAlias(antiAlias); 113366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); 11458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 115366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com fDraw.drawRect(rect, paint); 11658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 11758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkSafeUnref(mode); 11858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 11958b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 12058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com/** 12158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * Draw a single path element of the clip stack into the accumulation bitmap 12258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com */ 1235f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comvoid GrSWMaskHelper::draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op, 12412b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com bool antiAlias, uint8_t alpha) { 12558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 12658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkPaint paint; 1275f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (stroke.isHairlineStyle()) { 12858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com paint.setStyle(SkPaint::kStroke_Style); 12958b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com paint.setStrokeWidth(SK_Scalar1); 13058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com } else { 1315f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (stroke.isFillStyle()) { 13212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com paint.setStyle(SkPaint::kFill_Style); 13312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com } else { 13412b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com paint.setStyle(SkPaint::kStroke_Style); 13512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com paint.setStrokeJoin(stroke.getJoin()); 13612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com paint.setStrokeCap(stroke.getCap()); 1375f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com paint.setStrokeWidth(stroke.getWidth()); 13858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com } 13958b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com } 14058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com paint.setAntiAlias(antiAlias); 14158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 142b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski SkTBlitterAllocator allocator; 143b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski SkBlitter* blitter = NULL; 144b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski if (kBlitter_CompressionMode == fCompressionMode) { 14549f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fCompressedBuffer.get()); 146b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski blitter = SkTextureCompressor::CreateBlitterForFormat( 147b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fBM.width(), fBM.height(), fCompressedBuffer.get(), &allocator, fCompressedFormat); 148b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski } 149b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 150126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com if (SkRegion::kReplace_Op == op && 0xFF == alpha) { 151126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(0xFF == paint.getAlpha()); 152b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fDraw.drawPathCoverage(path, paint, blitter); 153126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } else { 154126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com paint.setXfermodeMode(op_to_mode(op)); 155126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); 156b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fDraw.drawPath(path, paint, blitter); 157126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 15858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 15958b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 160fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgbool GrSWMaskHelper::init(const SkIRect& resultBounds, 16171614ac7c63fe60dfe971f861e2b2d6325dd0039krajcevski const SkMatrix* matrix, 16271614ac7c63fe60dfe971f861e2b2d6325dd0039krajcevski bool allowCompression) { 16349f085dddff10473b6ebf832a974288300224e60bsalomon if (matrix) { 164366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com fMatrix = *matrix; 16558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com } else { 16658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com fMatrix.setIdentity(); 16758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com } 16858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 169366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com // Now translate so the bound's UL corner is at the origin 170366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1, 171366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com -resultBounds.fTop * SK_Scalar1); 172fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), 173366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com resultBounds.height()); 17425a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski 17571614ac7c63fe60dfe971f861e2b2d6325dd0039krajcevski if (allowCompression && 17671614ac7c63fe60dfe971f861e2b2d6325dd0039krajcevski fContext->getOptions().fDrawPathToCompressedTexture && 1779c6d4d744a9e0375d0e7d7a7b19558f5259fc3c3krajcevski choose_compressed_fmt(fContext->getGpu()->caps(), &fCompressedFormat)) { 178b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fCompressionMode = kCompress_CompressionMode; 179b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski } 18025a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski 181b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // Make sure that the width is a multiple of the desired block dimensions 182b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // to allow for specialized SIMD instructions that compress multiple blocks at a time. 183b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski int cmpWidth = bounds.fRight; 184b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski int cmpHeight = bounds.fBottom; 185b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski if (kCompress_CompressionMode == fCompressionMode) { 186b3abe90145b988883c9882de1ac42da963adbf67krajcevski int dimX, dimY; 187b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY); 188b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski cmpWidth = dimX * ((cmpWidth + (dimX - 1)) / dimX); 189b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski cmpHeight = dimY * ((cmpHeight + (dimY - 1)) / dimY); 190b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 191b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // Can we create a blitter? 192b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski if (SkTextureCompressor::ExistsBlitterForFormat(fCompressedFormat)) { 193b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski int cmpSz = SkTextureCompressor::GetCompressedDataSize( 194b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fCompressedFormat, cmpWidth, cmpHeight); 195b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 196b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski SkASSERT(cmpSz > 0); 197b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski SkASSERT(NULL == fCompressedBuffer.get()); 198b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fCompressedBuffer.reset(cmpSz); 199b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fCompressionMode = kBlitter_CompressionMode; 200b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski } 201b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski } 202b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 203b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // If we don't have a custom blitter, then we either need a bitmap to compress 204b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // from or a bitmap that we're going to use as a texture. In any case, we should 205b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // allocate the pixels for a bitmap 206b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(cmpWidth, cmpHeight); 207b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski if (kBlitter_CompressionMode != fCompressionMode) { 208848250415eddc54075f7eb8795e8db79e749c6abreed if (!fBM.tryAllocPixels(bmImageInfo)) { 209b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski return false; 210b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski } 21158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 212b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski sk_bzero(fBM.getPixels(), fBM.getSafeSize()); 213b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski } else { 214b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski // Otherwise, we just need to remember how big the buffer is... 215b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski fBM.setInfo(bmImageInfo); 21658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com } 217b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski 21858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com sk_bzero(&fDraw, sizeof(fDraw)); 219b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 22058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com fRasterClip.setRect(bounds); 22158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com fDraw.fRC = &fRasterClip; 22258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com fDraw.fClip = &fRasterClip.bwRgn(); 22358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com fDraw.fMatrix = &fMatrix; 22458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com fDraw.fBitmap = &fBM; 22558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com return true; 22658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 22758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 22858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com/** 229366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com * Get a texture (from the texture cache) of the correct size & format. 230366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com * Return true on success; false on failure. 23158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com */ 232366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.combool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) { 23358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com GrTextureDesc desc; 23458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com desc.fWidth = fBM.width(); 23558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com desc.fHeight = fBM.height(); 236b3abe90145b988883c9882de1ac42da963adbf67krajcevski desc.fConfig = kAlpha_8_GrPixelConfig; 237fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski 238b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski if (kNone_CompressionMode != fCompressionMode) { 239b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski 24025a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski#ifdef SK_DEBUG 241b3abe90145b988883c9882de1ac42da963adbf67krajcevski int dimX, dimY; 242b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY); 243b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkASSERT((desc.fWidth % dimX) == 0); 244b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkASSERT((desc.fHeight % dimY) == 0); 24525a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski#endif 24625a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski 247b3abe90145b988883c9882de1ac42da963adbf67krajcevski desc.fConfig = fmt_to_config(fCompressedFormat); 248b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski SkASSERT(fContext->getGpu()->caps()->isConfigTexturable(desc.fConfig)); 249fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski } 25058b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 251366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com texture->set(fContext, desc); 25249f085dddff10473b6ebf832a974288300224e60bsalomon return SkToBool(texture->texture()); 25358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 25458b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 255fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevskivoid GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrTextureDesc& desc, 256fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski const void *data, int rowbytes) { 257fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski // If we aren't reusing scratch textures we don't need to flush before 258fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski // writing since no one else will be using 'texture' 259fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures(); 2605c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski 261fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski // Since we're uploading to it, and it's compressed, 'texture' shouldn't 262fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski // have a render target. 263fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski SkASSERT(NULL == texture->asRenderTarget()); 264fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski 265fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski texture->writePixels(0, 0, desc.fWidth, desc.fHeight, 266fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski desc.fConfig, data, rowbytes, 267fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag); 2685c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski} 2695c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski 270b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevskivoid GrSWMaskHelper::compressTextureData(GrTexture *texture, const GrTextureDesc& desc) { 271b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski 272b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski SkASSERT(GrPixelConfigIsCompressed(desc.fConfig)); 273b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkASSERT(fmt_to_config(fCompressedFormat) == desc.fConfig); 274b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski 275b3abe90145b988883c9882de1ac42da963adbf67krajcevski SkAutoDataUnref cmpData(SkTextureCompressor::CompressBitmapToFormat(fBM, fCompressedFormat)); 27649f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(cmpData); 277b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski 278b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski this->sendTextureData(texture, desc, cmpData->data(), 0); 279b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski} 280b577c55a13850b8f4739e14b10d426a3ec6b05d0krajcevski 28158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com/** 28258b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com * Move the result of the software mask generation back to the gpu 28358b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com */ 284d92cf2ebbfbb9d737ea4a551e64ffccb08376875robertphillips@google.comvoid GrSWMaskHelper::toTexture(GrTexture *texture) { 28558b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com SkAutoLockPixels alp(fBM); 28658b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 287fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski GrTextureDesc desc; 288fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski desc.fWidth = fBM.width(); 289fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski desc.fHeight = fBM.height(); 290fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski desc.fConfig = texture->config(); 291fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski 292fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski // First see if we should compress this texture before uploading. 293b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski switch (fCompressionMode) { 294b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski case kNone_CompressionMode: 295b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski this->sendTextureData(texture, desc, fBM.getPixels(), fBM.rowBytes()); 296b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski break; 297b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 298b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski case kCompress_CompressionMode: 299b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski this->compressTextureData(texture, desc); 300b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski break; 301b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski 302b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski case kBlitter_CompressionMode: 30349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fCompressedBuffer.get()); 304b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski this->sendTextureData(texture, desc, fCompressedBuffer.get(), 0); 305b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski break; 306fb4f5cb39e31b8544b526074683a65bb716b7acfkrajcevski } 30758b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com} 30858b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com 309366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 310366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com/** 311fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * Software rasterizes path to A8 mask (possibly using the context's matrix) 3125dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com * and uploads the result to a scratch texture. Returns the resulting 3135dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com * texture on success; NULL on failure. 314366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com */ 3155dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.comGrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context, 3165dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com const SkPath& path, 3175f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 318fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& resultBounds, 3195dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com bool antiAlias, 320b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix* matrix) { 321366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com GrSWMaskHelper helper(context); 322366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 32384e922bfb3e7a03f6e35beb2f1e4f2657e7cd3e9reed@google.com if (!helper.init(resultBounds, matrix)) { 3245dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com return NULL; 325366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com } 326366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 32712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF); 328366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 3295c2fca040ec74617644554a46c39ab038afe2f1bkrajcevski GrAutoScratchTexture ast; 3305dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com if (!helper.getTexture(&ast)) { 3315dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com return NULL; 332366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com } 333366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 334d92cf2ebbfbb9d737ea4a551e64ffccb08376875robertphillips@google.com helper.toTexture(ast.texture()); 335366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 3365dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com return ast.detach(); 3375dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com} 3385dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com 3395dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.comvoid GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture, 3405dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com GrDrawTarget* target, 341fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& rect) { 3425dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com GrDrawState* drawState = target->drawState(); 3435dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com 344137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawState::AutoViewMatrixRestore avmr; 345137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com if (!avmr.setIdentity(drawState)) { 346e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return; 347e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com } 348eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com GrDrawState::AutoRestoreEffects are(drawState); 3495dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com 350fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft, 351fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SK_Scalar1 * rect.fTop, 352fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SK_Scalar1 * rect.fRight, 353fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SK_Scalar1 * rect.fBottom); 354c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com 355c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // We want to use device coords to compute the texture coordinates. We set our matrix to be 356c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // equal to the view matrix followed by a translation so that the top-left of the device bounds 357c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // maps to 0,0, and then a scaling matrix to normalized coords. We apply this matrix to the 358c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // vertex positions rather than local coords. 359c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com SkMatrix maskMatrix; 360c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com maskMatrix.setIDiv(texture->width(), texture->height()); 361c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop)); 362c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com maskMatrix.preConcat(drawState->getViewMatrix()); 363c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com 364b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->addCoverageProcessor( 365c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com GrSimpleTextureEffect::Create(texture, 366c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com maskMatrix, 367b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com GrTextureParams::kNone_FilterMode, 36877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com kPosition_GrCoordSet))->unref(); 369c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com 370c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com target->drawSimpleRect(dstRect); 371366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com} 372