blob: 3a01a7531782af3d9e430b504e87eb8bceb79df5 [file] [log] [blame]
Jason Sams326e0dd2009-05-22 14:03:28 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
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#include "rsContext.h"
18
19using namespace android;
20using namespace android::renderscript;
21
22Allocation::Allocation(const Type *type)
23{
24 mPtr = NULL;
25
26 mCpuWrite = false;
27 mCpuRead = false;
28 mGpuWrite = false;
29 mGpuRead = false;
30
31 mReadWriteRatio = 0;
32 mUpdateSize = 0;
33
34 mIsTexture = false;
35 mTextureID = 0;
36
37 mIsVertexBuffer = false;
38 mBufferID = 0;
39
40 mType.set(type);
41 mPtr = malloc(mType->getSizeBytes());
42 if (!mPtr) {
43 LOGE("Allocation::Allocation, alloc failure");
44 }
45
46}
47
48Allocation::~Allocation()
49{
Jason Sams565ac362009-06-03 16:04:54 -070050 LOGE("Allocation %p destryed", this);
Jason Sams326e0dd2009-05-22 14:03:28 -070051}
52
53void Allocation::setCpuWritable(bool)
54{
55}
56
57void Allocation::setGpuWritable(bool)
58{
59}
60
61void Allocation::setCpuReadable(bool)
62{
63}
64
65void Allocation::setGpuReadable(bool)
66{
67}
68
69bool Allocation::fixAllocation()
70{
71 return false;
72}
73
74void Allocation::uploadToTexture(uint32_t lodOffset)
75{
76 //rsAssert(!mTextureId);
77 rsAssert(lodOffset < mType->getLODCount());
78
79 //LOGE("uploadToTexture %i, lod %i", mTextureID, lodOffset);
80
Jason Sams565ac362009-06-03 16:04:54 -070081 GLenum type = mType->getElement()->getGLType();
82 GLenum format = mType->getElement()->getGLFormat();
83
84 if (!type || !format) {
85 return;
86 }
87
Jason Sams326e0dd2009-05-22 14:03:28 -070088 if (!mTextureID) {
89 glGenTextures(1, &mTextureID);
90 }
91 glBindTexture(GL_TEXTURE_2D, mTextureID);
92
93 Adapter2D adapt(this);
94 for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) {
95 adapt.setLOD(lod+lodOffset);
96
97 uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
Jason Sams565ac362009-06-03 16:04:54 -070098 glTexImage2D(GL_TEXTURE_2D, lod, format,
99 adapt.getDimX(), adapt.getDimY(),
100 0, format, type, ptr);
Jason Sams326e0dd2009-05-22 14:03:28 -0700101 }
102}
103
104void Allocation::uploadToBufferObject()
105{
106 rsAssert(!mType->getDimY());
107 rsAssert(!mType->getDimZ());
108
109 //LOGE("uploadToTexture %i, lod %i", mTextureID, lodOffset);
110
111 if (!mBufferID) {
112 glGenBuffers(1, &mBufferID);
113 }
114 glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
115 glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
116 glBindBuffer(GL_ARRAY_BUFFER, 0);
117}
118
119void Allocation::data(const void *data)
120{
121 memcpy(mPtr, data, mType->getSizeBytes());
122}
123
124void Allocation::subData(uint32_t xoff, uint32_t count, const void *data)
125{
126 uint32_t eSize = mType->getElementSizeBytes();
127 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
128 ptr += eSize * xoff;
129 memcpy(ptr, data, count * eSize);
130}
131
Jason Sams565ac362009-06-03 16:04:54 -0700132void Allocation::subData(uint32_t xoff, uint32_t yoff,
Jason Sams326e0dd2009-05-22 14:03:28 -0700133 uint32_t w, uint32_t h, const void *data)
134{
135 uint32_t eSize = mType->getElementSizeBytes();
136 uint32_t lineSize = eSize * w;
137 uint32_t destW = mType->getDimX();
138
139 const uint8_t *src = static_cast<const uint8_t *>(data);
140 uint8_t *dst = static_cast<uint8_t *>(mPtr);
141 dst += eSize * (xoff + yoff * destW);
142 for (uint32_t line=yoff; line < (yoff+h); line++) {
143 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
144 memcpy(dst, src, lineSize);
145 src += lineSize;
146 dst += destW * eSize;
147 }
148}
149
150void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
151 uint32_t w, uint32_t h, uint32_t d, const void *data)
152{
153}
154
155
156
157/////////////////
Jason Sams565ac362009-06-03 16:04:54 -0700158//
Jason Sams326e0dd2009-05-22 14:03:28 -0700159
160
161namespace android {
162namespace renderscript {
163
164RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
165{
166 const Type * type = static_cast<const Type *>(vtype);
167
168 Allocation * alloc = new Allocation(type);
169 return alloc;
170}
171
172RsAllocation rsi_AllocationCreatePredefSized(Context *rsc, RsElementPredefined t, size_t count)
173{
174 RsElement e = rsi_ElementGetPredefined(rsc, t);
175 return rsi_AllocationCreateSized(rsc, e, count);
176}
177
178RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
179{
180 Type * type = new Type();
181 type->setDimX(count);
182 type->setElement(static_cast<Element *>(e));
183 type->compute();
184 return rsi_AllocationCreateTyped(rsc, type);
185}
186
187void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel)
188{
189 Allocation *alloc = static_cast<Allocation *>(va);
190 alloc->uploadToTexture(baseMipLevel);
191}
192
193void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
194{
195 Allocation *alloc = static_cast<Allocation *>(va);
196 alloc->uploadToBufferObject();
197}
198
199void rsi_AllocationDestroy(Context *rsc, RsAllocation)
200{
201}
202
Jason Sams565ac362009-06-03 16:04:54 -0700203static void mip565(const Adapter2D &out, const Adapter2D &in)
Jason Sams326e0dd2009-05-22 14:03:28 -0700204{
205 uint32_t w = out.getDimX();
206 uint32_t h = out.getDimY();
207
208 for (uint32_t y=0; y < w; y++) {
209 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
210 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
211 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
212
213 for (uint32_t x=0; x < h; x++) {
Jason Sams565ac362009-06-03 16:04:54 -0700214 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
215 oPtr ++;
216 i1 += 2;
217 i2 += 2;
218 }
219 }
220}
221
222static void mip8888(const Adapter2D &out, const Adapter2D &in)
223{
224 uint32_t w = out.getDimX();
225 uint32_t h = out.getDimY();
226
227 for (uint32_t y=0; y < w; y++) {
228 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
229 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
230 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
231
232 for (uint32_t x=0; x < h; x++) {
233 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
Jason Sams326e0dd2009-05-22 14:03:28 -0700234 oPtr ++;
235 i1 += 2;
236 i2 += 2;
237 }
238 }
239
240}
241
242
Jason Sams6678e9b2009-05-27 14:45:32 -0700243typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
244
245static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
246{
247 memcpy(dst, src, count * 2);
248}
249static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
250{
251 memcpy(dst, src, count);
252}
253static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
254{
255 memcpy(dst, src, count * 4);
256}
257
258
259static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
260{
261 uint16_t *d = static_cast<uint16_t *>(dst);
262 const uint8_t *s = static_cast<const uint8_t *>(src);
263
264 while(count--) {
265 *d = rs888to565(s[0], s[1], s[2]);
266 d++;
267 s+= 3;
268 }
269}
270
271static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
272{
273 uint16_t *d = static_cast<uint16_t *>(dst);
274 const uint8_t *s = static_cast<const uint8_t *>(src);
275
276 while(count--) {
277 *d = rs888to565(s[0], s[1], s[2]);
278 d++;
279 s+= 4;
280 }
281}
282
283static ElementConverter_t pickConverter(RsElementPredefined dstFmt, RsElementPredefined srcFmt)
284{
Jason Sams565ac362009-06-03 16:04:54 -0700285 if ((dstFmt == RS_ELEMENT_RGB_565) &&
Jason Sams6678e9b2009-05-27 14:45:32 -0700286 (srcFmt == RS_ELEMENT_RGB_565)) {
287 return elementConverter_cpy_16;
288 }
289
Jason Sams565ac362009-06-03 16:04:54 -0700290 if ((dstFmt == RS_ELEMENT_RGB_565) &&
Jason Sams6678e9b2009-05-27 14:45:32 -0700291 (srcFmt == RS_ELEMENT_RGB_888)) {
292 return elementConverter_888_to_565;
293 }
294
Jason Sams565ac362009-06-03 16:04:54 -0700295 if ((dstFmt == RS_ELEMENT_RGB_565) &&
Jason Sams6678e9b2009-05-27 14:45:32 -0700296 (srcFmt == RS_ELEMENT_RGBA_8888)) {
297 return elementConverter_8888_to_565;
298 }
299
Jason Sams565ac362009-06-03 16:04:54 -0700300 if ((dstFmt == RS_ELEMENT_RGBA_8888) &&
301 (srcFmt == RS_ELEMENT_RGBA_8888)) {
302 return elementConverter_cpy_32;
303 }
Jason Sams6678e9b2009-05-27 14:45:32 -0700304
305 LOGE("pickConverter, unsuported combo");
306 return 0;
307}
308
309
310RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data)
311{
312 rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565));
313 rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
314 rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
315 if (genMips) {
316 rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
317 }
318 RsType type = rsi_TypeCreate(rsc);
319
320 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
321 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
322 if (texAlloc == NULL) {
323 LOGE("Memory allocation failure");
324 return NULL;
325 }
326 texAlloc->incRef();
327
328 ElementConverter_t cvt = pickConverter(dstFmt, srcFmt);
329 cvt(texAlloc->getPtr(), data, w * h);
330
331 if (genMips) {
332 Adapter2D adapt(texAlloc);
333 Adapter2D adapt2(texAlloc);
334 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
335 adapt.setLOD(lod);
336 adapt2.setLOD(lod + 1);
Jason Sams565ac362009-06-03 16:04:54 -0700337 mip565(adapt2, adapt);
Jason Sams6678e9b2009-05-27 14:45:32 -0700338 }
339 }
340
341 return texAlloc;
342}
343
344RsAllocation rsi_AllocationCreateFromFile(Context *rsc, const char *file, bool genMips)
Jason Sams326e0dd2009-05-22 14:03:28 -0700345{
Jason Sams565ac362009-06-03 16:04:54 -0700346 bool use32bpp = false;
347
Jason Sams326e0dd2009-05-22 14:03:28 -0700348 typedef struct _Win3xBitmapHeader
349 {
350 uint16_t type;
351 uint32_t totalSize;
352 uint32_t reserved;
353 uint32_t offset;
354 int32_t hdrSize; /* Size of this header in bytes */
355 int32_t width; /* Image width in pixels */
356 int32_t height; /* Image height in pixels */
357 int16_t planes; /* Number of color planes */
358 int16_t bpp; /* Number of bits per pixel */
359 /* Fields added for Windows 3.x follow this line */
360 int32_t compression; /* Compression methods used */
361 int32_t sizeOfBitmap; /* Size of bitmap in bytes */
362 int32_t horzResolution; /* Horizontal resolution in pixels per meter */
363 int32_t vertResolution; /* Vertical resolution in pixels per meter */
364 int32_t colorsUsed; /* Number of colors in the image */
365 int32_t colorsImportant; /* Minimum number of important colors */
366 } __attribute__((__packed__)) WIN3XBITMAPHEADER;
367
368 _Win3xBitmapHeader hdr;
369
370 FILE *f = fopen(file, "rb");
371 if (f == NULL) {
372 LOGE("rsAllocationCreateFromBitmap failed to open file %s", file);
373 return NULL;
374 }
375 memset(&hdr, 0, sizeof(hdr));
376 fread(&hdr, sizeof(hdr), 1, f);
377
378 if (hdr.bpp != 24) {
379 LOGE("Unsuported BMP type");
380 fclose(f);
381 return NULL;
382 }
383
384 int32_t texWidth = rsHigherPow2(hdr.width);
385 int32_t texHeight = rsHigherPow2(hdr.height);
386
Jason Sams565ac362009-06-03 16:04:54 -0700387 if (use32bpp) {
388 rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGBA_8888));
389 } else {
390 rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565));
391 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700392 rsi_TypeAdd(rsc, RS_DIMENSION_X, texWidth);
393 rsi_TypeAdd(rsc, RS_DIMENSION_Y, texHeight);
394 if (genMips) {
395 rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
396 }
397 RsType type = rsi_TypeCreate(rsc);
398
399 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
400 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
401 texAlloc->incRef();
402 if (texAlloc == NULL) {
403 LOGE("Memory allocation failure");
404 fclose(f);
405 return NULL;
406 }
407
408 // offset to letterbox if height is not pow2
409 Adapter2D adapt(texAlloc);
410 uint8_t * fileInBuf = new uint8_t[texWidth * 3];
411 uint32_t yOffset = (hdr.width - hdr.height) / 2;
Jason Sams326e0dd2009-05-22 14:03:28 -0700412
Jason Sams565ac362009-06-03 16:04:54 -0700413 if (use32bpp) {
414 uint8_t *tmp = static_cast<uint8_t *>(adapt.getElement(0, yOffset));
415 for (int y=0; y < hdr.height; y++) {
416 fseek(f, hdr.offset + (y*hdr.width*3), SEEK_SET);
417 fread(fileInBuf, 1, hdr.width * 3, f);
418 for(int x=0; x < hdr.width; x++) {
419 tmp[0] = fileInBuf[x*3 + 2];
420 tmp[1] = fileInBuf[x*3 + 1];
421 tmp[2] = fileInBuf[x*3];
422 tmp[3] = 0xff;
423 tmp += 4;
424 }
425 }
426 } else {
427 uint16_t *tmp = static_cast<uint16_t *>(adapt.getElement(0, yOffset));
428 for (int y=0; y < hdr.height; y++) {
429 fseek(f, hdr.offset + (y*hdr.width*3), SEEK_SET);
430 fread(fileInBuf, 1, hdr.width * 3, f);
431 for(int x=0; x < hdr.width; x++) {
432 *tmp = rs888to565(fileInBuf[x*3 + 2], fileInBuf[x*3 + 1], fileInBuf[x*3]);
433 tmp++;
434 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700435 }
436 }
437
438 fclose(f);
439 delete [] fileInBuf;
440
441 if (genMips) {
442 Adapter2D adapt2(texAlloc);
443 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
444 adapt.setLOD(lod);
445 adapt2.setLOD(lod + 1);
Jason Sams565ac362009-06-03 16:04:54 -0700446 if (use32bpp) {
447 mip8888(adapt2, adapt);
448 } else {
449 mip565(adapt2, adapt);
450 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700451 }
452 }
453
454 return texAlloc;
455}
456
457
458void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data)
459{
460 Allocation *a = static_cast<Allocation *>(va);
461 a->data(data);
462}
463
464void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data)
465{
466 Allocation *a = static_cast<Allocation *>(va);
467 a->subData(xoff, count, data);
468}
469
470void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data)
471{
472 Allocation *a = static_cast<Allocation *>(va);
473 a->subData(xoff, yoff, w, h, data);
474}
475
476
477}
478}