blob: 4f1e6fd2ab347233acb3088e51544372f69779ba [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "SkGr.h"
19
20/* Fill out buffer with the compressed format Ganesh expects from a colortable
21 based bitmap. [palette (colortable) + indices].
bsalomon@google.com5782d712011-01-21 21:03:59 +000022
23 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
reed@google.comac10a2d2010-12-22 21:39:39 +000024 we could detect that the colortable.count is <= 16, and then repack the
25 indices as nibbles to save RAM, but it would take more time (i.e. a lot
26 slower than memcpy), so skipping that for now.
bsalomon@google.com5782d712011-01-21 21:03:59 +000027
reed@google.comac10a2d2010-12-22 21:39:39 +000028 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
29 as the colortable.count says it is.
30 */
31static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
32 SkASSERT(SkBitmap::kIndex8_Config == bitmap.config());
bsalomon@google.com5782d712011-01-21 21:03:59 +000033
reed@google.comac10a2d2010-12-22 21:39:39 +000034 SkAutoLockPixels apl(bitmap);
35 if (!bitmap.readyToDraw()) {
36 SkASSERT(!"bitmap not ready to draw!");
37 return;
38 }
39
40 SkColorTable* ctable = bitmap.getColorTable();
41 char* dst = (char*)buffer;
bsalomon@google.com5782d712011-01-21 21:03:59 +000042
reed@google.comac10a2d2010-12-22 21:39:39 +000043 memcpy(dst, ctable->lockColors(), ctable->count() * sizeof(SkPMColor));
44 ctable->unlockColors(false);
bsalomon@google.com5782d712011-01-21 21:03:59 +000045
reed@google.comac10a2d2010-12-22 21:39:39 +000046 // always skip a full 256 number of entries, even if we memcpy'd fewer
bsalomon@google.comfea37b52011-04-25 15:51:06 +000047 dst += kGrColorTableSize;
reed@google.comac10a2d2010-12-22 21:39:39 +000048
49 if (bitmap.width() == bitmap.rowBytes()) {
50 memcpy(dst, bitmap.getPixels(), bitmap.getSize());
51 } else {
52 // need to trim off the extra bytes per row
53 size_t width = bitmap.width();
54 size_t rowBytes = bitmap.rowBytes();
55 const char* src = (const char*)bitmap.getPixels();
56 for (int y = 0; y < bitmap.height(); y++) {
57 memcpy(dst, src, width);
58 src += rowBytes;
59 dst += width;
60 }
61 }
62}
63
64////////////////////////////////////////////////////////////////////////////////
65
bsalomon@google.com5782d712011-01-21 21:03:59 +000066GrTextureEntry* sk_gr_create_bitmap_texture(GrContext* ctx,
reed@google.comac10a2d2010-12-22 21:39:39 +000067 GrTextureKey* key,
68 const GrSamplerState& sampler,
69 const SkBitmap& origBitmap) {
70 SkAutoLockPixels alp(origBitmap);
71 if (!origBitmap.readyToDraw()) {
72 return NULL;
73 }
74
75 SkBitmap tmpBitmap;
76
77 const SkBitmap* bitmap = &origBitmap;
bsalomon@google.com5782d712011-01-21 21:03:59 +000078
bsalomon@google.comfea37b52011-04-25 15:51:06 +000079 GrTextureDesc desc = {
80 kNone_GrTextureFlags,
81 kNone_GrAALevel,
reed@google.comac10a2d2010-12-22 21:39:39 +000082 bitmap->width(),
83 bitmap->height(),
84 SkGr::Bitmap2PixelConfig(*bitmap)
85 };
bsalomon@google.com5782d712011-01-21 21:03:59 +000086
reed@google.comac10a2d2010-12-22 21:39:39 +000087 if (SkBitmap::kIndex8_Config == bitmap->config()) {
88 // build_compressed_data doesn't do npot->pot expansion
89 // and paletted textures can't be sub-updated
90 if (ctx->supportsIndex8PixelConfig(sampler,
91 bitmap->width(), bitmap->height())) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000092 size_t imagesize = bitmap->width() * bitmap->height() +
bsalomon@google.comfea37b52011-04-25 15:51:06 +000093 kGrColorTableSize;
reed@google.comac10a2d2010-12-22 21:39:39 +000094 SkAutoMalloc storage(imagesize);
bsalomon@google.com5782d712011-01-21 21:03:59 +000095
reed@google.comac10a2d2010-12-22 21:39:39 +000096 build_compressed_data(storage.get(), origBitmap);
97
98 // our compressed data will be trimmed, so pass width() for its
99 // "rowBytes", since they are the same now.
junov@google.com4ee7ae52011-06-30 17:30:49 +0000100
101 if (NULL != key) {
102 return ctx->createAndLockTexture(key, sampler, desc, storage.get(),
103 bitmap->width());
104 } else {
105 GrTextureEntry* entry = ctx->lockKeylessTexture(desc);
106 entry->texture()->uploadTextureData(0, 0, bitmap->width(),
107 bitmap->height(), storage.get(), 0);
108 return entry;
109 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000110
111 } else {
112 origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config);
113 // now bitmap points to our temp, which has been promoted to 32bits
114 bitmap = &tmpBitmap;
115 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000116 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000117
118 desc.fFormat = SkGr::Bitmap2PixelConfig(*bitmap);
junov@google.com4ee7ae52011-06-30 17:30:49 +0000119 if (NULL != key) {
120 return ctx->createAndLockTexture(key, sampler, desc,
121 bitmap->getPixels(), bitmap->rowBytes());
122 } else {
123 GrTextureEntry* entry = ctx->lockKeylessTexture(desc);
124 entry->texture()->uploadTextureData(0, 0, bitmap->width(),
125 bitmap->height(), bitmap->getPixels(), bitmap->rowBytes());
126 return entry;
127 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000128}
129
reed@google.comac10a2d2010-12-22 21:39:39 +0000130///////////////////////////////////////////////////////////////////////////////
131
bsalomon@google.comd302f142011-03-03 13:54:13 +0000132void SkGrClipIterator::reset(const SkClipStack& clipStack) {
133 fClipStack = &clipStack;
134 fIter.reset(clipStack);
135 // Gr has no notion of replace, skip to the
136 // last replace in the clip stack.
137 int lastReplace = 0;
138 int curr = 0;
139 while (NULL != (fCurr = fIter.next())) {
140 if (SkRegion::kReplace_Op == fCurr->fOp) {
141 lastReplace = curr;
142 }
143 ++curr;
144 }
145 fIter.reset(clipStack);
146 for (int i = 0; i < lastReplace+1; ++i) {
147 fCurr = fIter.next();
148 }
149}
150
151GrClipType SkGrClipIterator::getType() const {
152 GrAssert(!this->isDone());
scroggo7b118072011-03-23 15:04:26 +0000153 if (NULL == fCurr->fPath) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000154 return kRect_ClipType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000155 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000156 return kPath_ClipType;
157 }
158}
159
160GrSetOp SkGrClipIterator::getOp() const {
161 // we skipped to the last "replace" op
162 // when this iter was reset.
163 // GrClip doesn't allow replace, so treat it as
164 // intersect.
165 GrSetOp skToGrOps[] = {
166 kDifference_SetOp, // kDifference_Op
167 kIntersect_SetOp, // kIntersect_Op
168 kUnion_SetOp, // kUnion_Op
169 kXor_SetOp, // kXOR_Op
170 kReverseDifference_SetOp, // kReverseDifference_Op
171 kIntersect_SetOp // kReplace_op
172 };
173 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
174 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
175 GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
176 GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
177 GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
178 GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
179 return skToGrOps[fCurr->fOp];
180}
181
182GrPathFill SkGrClipIterator::getPathFill() const {
183 switch (fCurr->fPath->getFillType()) {
184 case SkPath::kWinding_FillType:
185 return kWinding_PathFill;
186 case SkPath::kEvenOdd_FillType:
187 return kEvenOdd_PathFill;
188 case SkPath::kInverseWinding_FillType:
189 return kInverseWinding_PathFill;
190 case SkPath::kInverseEvenOdd_FillType:
191 return kInverseEvenOdd_PathFill;
192 default:
193 GrCrash("Unsupported path fill in clip.");
194 return kWinding_PathFill; // suppress warning
reed@google.comac10a2d2010-12-22 21:39:39 +0000195 }
196}
197
198///////////////////////////////////////////////////////////////////////////////
199
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000200GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config,
reed@google.comac10a2d2010-12-22 21:39:39 +0000201 bool isOpaque) {
202 switch (config) {
203 case SkBitmap::kA8_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000204 return kAlpha_8_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000205 case SkBitmap::kIndex8_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000206 return kIndex_8_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000207 case SkBitmap::kRGB_565_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000208 return kRGB_565_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000209 case SkBitmap::kARGB_4444_Config:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000210 return kRGBA_4444_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 case SkBitmap::kARGB_8888_Config:
212 if (isOpaque) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000213 return kRGBX_8888_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000214 } else {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000215 return kRGBA_8888_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 }
217 default:
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000218 return kUnknown_GrPixelConfig;
reed@google.comac10a2d2010-12-22 21:39:39 +0000219 }
220}
221