blob: 41cf1bd520f2f779a19bdecd9805a2f082ed2648 [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
47 dst += GrGpu::kColorTableSize;
48
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
reed@google.comac10a2d2010-12-22 21:39:39 +000079 GrGpu::TextureDesc desc = {
80 0,
81 GrGpu::kNone_AALevel,
82 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() +
reed@google.comac10a2d2010-12-22 21:39:39 +000093 GrGpu::kColorTableSize;
94 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.
100 return ctx->createAndLockTexture(key, sampler, desc, storage.get(),
101 bitmap->width());
102
103 } else {
104 origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config);
105 // now bitmap points to our temp, which has been promoted to 32bits
106 bitmap = &tmpBitmap;
107 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000108 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000109
110 desc.fFormat = SkGr::Bitmap2PixelConfig(*bitmap);
111 return ctx->createAndLockTexture(key, sampler, desc, bitmap->getPixels(),
112 bitmap->rowBytes());
113}
114
115////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000116
reed@google.comac10a2d2010-12-22 21:39:39 +0000117
118SkGrPathIter::Command SkGrPathIter::next(GrPoint pts[]) {
119 GrAssert(NULL != pts);
120#if SK_SCALAR_IS_GR_SCALAR
121 return sk_path_verb_to_gr_path_command(fIter.next((SkPoint*)pts));
122#else
123 Command cmd = sk_path_verb_to_gr_path_command(fIter.next(fPoints));
124 int n = NumCommandPoints(cmd);
125 for (int i = 0; i < n; ++i) {
126 pts[i].fX = SkScalarToGrScalar(fPoints[i].fX);
127 pts[i].fY = SkScalarToGrScalar(fPoints[i].fY);
128 }
129 return cmd;
130#endif
131}
132
133SkGrPathIter::Command SkGrPathIter::next() {
134 return sk_path_verb_to_gr_path_command(fIter.next(NULL));
135}
136
137void SkGrPathIter::rewind() {
138 fIter.setPath(fPath, false);
139}
140
141GrPathIter::ConvexHint SkGrPathIter::hint() const {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000142 return fPath.isConvex() ? GrPathIter::kConvex_ConvexHint :
reed@google.comac10a2d2010-12-22 21:39:39 +0000143 GrPathIter::kNone_ConvexHint;
144}
145
146///////////////////////////////////////////////////////////////////////////////
147
148void SkGrClipIterator::computeBounds(GrIRect* bounds) {
149 const SkRegion* rgn = fIter.rgn();
150 if (rgn) {
151 SkGr::SetIRect(bounds, rgn->getBounds());
152 } else {
153 bounds->setEmpty();
154 }
155}
156
157///////////////////////////////////////////////////////////////////////////////
158
159GrTexture::PixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config,
160 bool isOpaque) {
161 switch (config) {
162 case SkBitmap::kA8_Config:
163 return GrTexture::kAlpha_8_PixelConfig;
164 case SkBitmap::kIndex8_Config:
165 return GrTexture::kIndex_8_PixelConfig;
166 case SkBitmap::kRGB_565_Config:
167 return GrTexture::kRGB_565_PixelConfig;
168 case SkBitmap::kARGB_4444_Config:
169 return GrTexture::kRGBA_4444_PixelConfig;
170 case SkBitmap::kARGB_8888_Config:
171 if (isOpaque) {
172 return GrTexture::kRGBX_8888_PixelConfig;
173 } else {
174 return GrTexture::kRGBA_8888_PixelConfig;
175 }
176 default:
177 return GrTexture::kUnknown_PixelConfig;
178 }
179}
180
181void SkGr::AbandonAllTextures(GrContext* ctx) {
182 ctx->abandonAllTextures();
183}
184
185