blob: b74fa8ef34920011f39351de65bfc6650d5bcf7d [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 */
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -070016#ifndef ANDROID_RS_BUILD_FOR_HOST
Jason Sams326e0dd2009-05-22 14:03:28 -070017#include "rsContext.h"
18
Jason Sams1aa5a4e2009-06-22 17:15:15 -070019#include <GLES/gl.h>
Jason Sams7fabe1a2010-02-23 17:44:28 -080020#include <GLES2/gl2.h>
Jason Sams1aa5a4e2009-06-22 17:15:15 -070021#include <GLES/glext.h>
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -070022#else
23#include "rsContextHostStub.h"
24
25#include <OpenGL/gl.h>
26#include <OpenGl/glext.h>
27#endif
Jason Sams1aa5a4e2009-06-22 17:15:15 -070028
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -070029#include "utils/StopWatch.h"
30
Jason Sams326e0dd2009-05-22 14:03:28 -070031using namespace android;
32using namespace android::renderscript;
33
Jason Samse514b452009-09-25 14:51:22 -070034Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc)
Jason Sams326e0dd2009-05-22 14:03:28 -070035{
Jason Samsfa84da22010-03-01 15:31:04 -080036 init(rsc, type);
37
38 mPtr = malloc(mType->getSizeBytes());
Jason Sams10e5e572010-08-12 12:44:02 -070039 if (mType->getElement()->getHasReferences()) {
40 memset(mPtr, 0, mType->getSizeBytes());
41 }
Jason Samsfa84da22010-03-01 15:31:04 -080042 if (!mPtr) {
43 LOGE("Allocation::Allocation, alloc failure");
44 }
45}
46
47Allocation::Allocation(Context *rsc, const Type *type, void *bmp,
48 void *callbackData, RsBitmapCallback_t callback)
49: ObjectBase(rsc)
50{
51 init(rsc, type);
52
53 mPtr = bmp;
54 mUserBitmapCallback = callback;
55 mUserBitmapCallbackData = callbackData;
56}
57
58void Allocation::init(Context *rsc, const Type *type)
59{
Jason Sams326e0dd2009-05-22 14:03:28 -070060 mPtr = NULL;
61
62 mCpuWrite = false;
63 mCpuRead = false;
64 mGpuWrite = false;
65 mGpuRead = false;
66
67 mReadWriteRatio = 0;
68 mUpdateSize = 0;
69
70 mIsTexture = false;
71 mTextureID = 0;
Jason Sams326e0dd2009-05-22 14:03:28 -070072 mIsVertexBuffer = false;
73 mBufferID = 0;
Jason Samscf4c7c92009-12-14 12:57:40 -080074 mUploadDefered = false;
Jason Sams326e0dd2009-05-22 14:03:28 -070075
Jason Samsfa84da22010-03-01 15:31:04 -080076 mUserBitmapCallback = NULL;
77 mUserBitmapCallbackData = NULL;
78
Jason Sams326e0dd2009-05-22 14:03:28 -070079 mType.set(type);
Jason Samse5ffb872009-08-09 17:01:55 -070080 rsAssert(type);
Jason Samsfa84da22010-03-01 15:31:04 -080081
82 mPtr = NULL;
Jason Sams326e0dd2009-05-22 14:03:28 -070083}
84
85Allocation::~Allocation()
86{
Jason Samsfa84da22010-03-01 15:31:04 -080087 if (mUserBitmapCallback != NULL) {
88 mUserBitmapCallback(mUserBitmapCallbackData);
89 } else {
90 free(mPtr);
91 }
Jason Samsbf3c14e2009-11-02 14:25:10 -080092 mPtr = NULL;
Jason Samse402ed32009-11-03 11:25:42 -080093
94 if (mBufferID) {
95 // Causes a SW crash....
96 //LOGV(" mBufferID %i", mBufferID);
97 //glDeleteBuffers(1, &mBufferID);
98 //mBufferID = 0;
99 }
100 if (mTextureID) {
101 glDeleteTextures(1, &mTextureID);
102 mTextureID = 0;
103 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700104}
105
106void Allocation::setCpuWritable(bool)
107{
108}
109
110void Allocation::setGpuWritable(bool)
111{
112}
113
114void Allocation::setCpuReadable(bool)
115{
116}
117
118void Allocation::setGpuReadable(bool)
119{
120}
121
122bool Allocation::fixAllocation()
123{
124 return false;
125}
126
Jason Sams7fabe1a2010-02-23 17:44:28 -0800127void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset)
Jason Samscf4c7c92009-12-14 12:57:40 -0800128{
129 rsAssert(lodOffset < mType->getLODCount());
130 mIsTexture = true;
131 mTextureLOD = lodOffset;
132 mUploadDefered = true;
Jason Sams7fabe1a2010-02-23 17:44:28 -0800133 mTextureGenMipmap = !mType->getDimLOD() && genMipmap;
Jason Samscf4c7c92009-12-14 12:57:40 -0800134}
135
136void Allocation::uploadToTexture(const Context *rsc)
Jason Sams326e0dd2009-05-22 14:03:28 -0700137{
138 //rsAssert(!mTextureId);
Jason Samscf4c7c92009-12-14 12:57:40 -0800139
140 mIsTexture = true;
141 if (!rsc->checkDriver()) {
142 mUploadDefered = true;
143 return;
144 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700145
Jason Samsd01d9702009-12-23 14:35:29 -0800146 GLenum type = mType->getElement()->getComponent().getGLType();
147 GLenum format = mType->getElement()->getComponent().getGLFormat();
Jason Sams565ac362009-06-03 16:04:54 -0700148
149 if (!type || !format) {
150 return;
151 }
152
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700153 bool isFirstUpload = false;
154
Jason Sams326e0dd2009-05-22 14:03:28 -0700155 if (!mTextureID) {
156 glGenTextures(1, &mTextureID);
Jason Sams13e26342009-11-24 12:26:35 -0800157
158 if (!mTextureID) {
159 // This should not happen, however, its likely the cause of the
160 // white sqare bug.
161 // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
162 LOGE("Upload to texture failed to gen mTextureID");
163 rsc->dumpDebug();
Jason Samscf4c7c92009-12-14 12:57:40 -0800164 mUploadDefered = true;
165 return;
Jason Sams13e26342009-11-24 12:26:35 -0800166 }
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700167 isFirstUpload = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700168 }
169 glBindTexture(GL_TEXTURE_2D, mTextureID);
Jason Sams5f0b4e12009-11-05 12:44:58 -0800170 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Jason Sams326e0dd2009-05-22 14:03:28 -0700171
Jason Samse514b452009-09-25 14:51:22 -0700172 Adapter2D adapt(getContext(), this);
Jason Samscf4c7c92009-12-14 12:57:40 -0800173 for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
174 adapt.setLOD(lod+mTextureLOD);
Jason Sams326e0dd2009-05-22 14:03:28 -0700175
176 uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700177 if(isFirstUpload) {
178 glTexImage2D(GL_TEXTURE_2D, lod, format,
179 adapt.getDimX(), adapt.getDimY(),
180 0, format, type, ptr);
181 } else {
182 glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
183 adapt.getDimX(), adapt.getDimY(),
184 format, type, ptr);
185 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700186 }
Jason Sams7fabe1a2010-02-23 17:44:28 -0800187 if (mTextureGenMipmap) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700188#ifndef ANDROID_RS_BUILD_FOR_HOST
Jason Sams7fabe1a2010-02-23 17:44:28 -0800189 glGenerateMipmap(GL_TEXTURE_2D);
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700190#endif //ANDROID_RS_BUILD_FOR_HOST
Jason Sams7fabe1a2010-02-23 17:44:28 -0800191 }
192
Jason Samsc1ed5892010-03-10 17:30:41 -0800193 rsc->checkError("Allocation::uploadToTexture");
Jason Sams326e0dd2009-05-22 14:03:28 -0700194}
195
Jason Samscf4c7c92009-12-14 12:57:40 -0800196void Allocation::deferedUploadToBufferObject(const Context *rsc)
197{
198 mIsVertexBuffer = true;
199 mUploadDefered = true;
200}
201
202void Allocation::uploadToBufferObject(const Context *rsc)
Jason Sams326e0dd2009-05-22 14:03:28 -0700203{
204 rsAssert(!mType->getDimY());
205 rsAssert(!mType->getDimZ());
206
Jason Samscf4c7c92009-12-14 12:57:40 -0800207 mIsVertexBuffer = true;
208 if (!rsc->checkDriver()) {
209 mUploadDefered = true;
210 return;
211 }
212
Jason Sams326e0dd2009-05-22 14:03:28 -0700213 if (!mBufferID) {
214 glGenBuffers(1, &mBufferID);
215 }
Jason Samscf4c7c92009-12-14 12:57:40 -0800216 if (!mBufferID) {
217 LOGE("Upload to buffer object failed");
218 mUploadDefered = true;
219 return;
220 }
221
Jason Sams326e0dd2009-05-22 14:03:28 -0700222 glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
223 glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
224 glBindBuffer(GL_ARRAY_BUFFER, 0);
Jason Samsc1ed5892010-03-10 17:30:41 -0800225 rsc->checkError("Allocation::uploadToBufferObject");
Jason Sams326e0dd2009-05-22 14:03:28 -0700226}
227
Jason Samscf4c7c92009-12-14 12:57:40 -0800228void Allocation::uploadCheck(const Context *rsc)
229{
230 if (mUploadDefered) {
231 mUploadDefered = false;
232 if (mIsVertexBuffer) {
233 uploadToBufferObject(rsc);
234 }
235 if (mIsTexture) {
236 uploadToTexture(rsc);
237 }
238 }
239}
240
Jason Samse5ffb872009-08-09 17:01:55 -0700241
Jason Sams5f0c84c2010-08-31 13:50:42 -0700242void Allocation::data(Context *rsc, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700243{
Jason Sams9397e302009-08-27 20:23:34 -0700244 uint32_t size = mType->getSizeBytes();
245 if (size != sizeBytes) {
246 LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
247 return;
248 }
Jason Samse3929c92010-08-09 18:13:33 -0700249
250 if (mType->getElement()->getHasReferences()) {
251 incRefs(data, sizeBytes / mType->getElement()->getSizeBytes());
252 decRefs(mPtr, sizeBytes / mType->getElement()->getSizeBytes());
253 }
254
Jason Sams9397e302009-08-27 20:23:34 -0700255 memcpy(mPtr, data, size);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700256 sendDirty();
Jason Samscf4c7c92009-12-14 12:57:40 -0800257 mUploadDefered = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700258}
259
Jason Samse579df42009-08-10 14:55:26 -0700260void Allocation::read(void *data)
261{
262 memcpy(data, mPtr, mType->getSizeBytes());
263}
264
Jason Sams5f0c84c2010-08-31 13:50:42 -0700265void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700266{
267 uint32_t eSize = mType->getElementSizeBytes();
268 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
269 ptr += eSize * xoff;
Jason Sams9397e302009-08-27 20:23:34 -0700270 uint32_t size = count * eSize;
271
272 if (size != sizeBytes) {
273 LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
Jason Samse12c1c52009-09-27 17:50:38 -0700274 mType->dumpLOGV("type info");
Jason Sams9397e302009-08-27 20:23:34 -0700275 return;
276 }
Jason Samse3929c92010-08-09 18:13:33 -0700277
278 if (mType->getElement()->getHasReferences()) {
279 incRefs(data, count);
280 decRefs(ptr, count);
281 }
282
Jason Sams9397e302009-08-27 20:23:34 -0700283 memcpy(ptr, data, size);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700284 sendDirty();
Jason Samscf4c7c92009-12-14 12:57:40 -0800285 mUploadDefered = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700286}
287
Jason Sams5f0c84c2010-08-31 13:50:42 -0700288void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff,
Jason Sams9397e302009-08-27 20:23:34 -0700289 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700290{
291 uint32_t eSize = mType->getElementSizeBytes();
292 uint32_t lineSize = eSize * w;
293 uint32_t destW = mType->getDimX();
294
295 const uint8_t *src = static_cast<const uint8_t *>(data);
296 uint8_t *dst = static_cast<uint8_t *>(mPtr);
297 dst += eSize * (xoff + yoff * destW);
Jason Sams9397e302009-08-27 20:23:34 -0700298
299 if ((lineSize * eSize * h) != sizeBytes) {
300 rsAssert(!"Allocation::subData called with mismatched size");
301 return;
302 }
303
Jason Sams326e0dd2009-05-22 14:03:28 -0700304 for (uint32_t line=yoff; line < (yoff+h); line++) {
Jason Samse3929c92010-08-09 18:13:33 -0700305 if (mType->getElement()->getHasReferences()) {
306 incRefs(src, w);
307 decRefs(dst, w);
308 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700309 memcpy(dst, src, lineSize);
310 src += lineSize;
311 dst += destW * eSize;
312 }
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700313 sendDirty();
Jason Samscf4c7c92009-12-14 12:57:40 -0800314 mUploadDefered = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700315}
316
Jason Sams5f0c84c2010-08-31 13:50:42 -0700317void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
Jason Sams9397e302009-08-27 20:23:34 -0700318 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700319{
320}
321
Jason Sams5f0c84c2010-08-31 13:50:42 -0700322void Allocation::subElementData(Context *rsc, uint32_t x, const void *data,
323 uint32_t cIdx, uint32_t sizeBytes)
324{
325 uint32_t eSize = mType->getElementSizeBytes();
326 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
327 ptr += eSize * x;
328
329 if (cIdx >= mType->getElement()->getFieldCount()) {
330 LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
331 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
332 return;
333 }
334
335 if (x >= mType->getDimX()) {
336 LOGE("Error Allocation::subElementData X offset %i out of range.", x);
337 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
338 return;
339 }
340
341 const Element * e = mType->getElement()->getField(cIdx);
342 ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
343
344 if (sizeBytes != e->getSizeBytes()) {
345 LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
346 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
347 return;
348 }
349
350 if (e->getHasReferences()) {
351 e->incRefs(data);
352 e->decRefs(ptr);
353 }
354
355 memcpy(ptr, data, sizeBytes);
356 sendDirty();
357 mUploadDefered = true;
358}
359
360void Allocation::subElementData(Context *rsc, uint32_t x, uint32_t y,
361 const void *data, uint32_t cIdx, uint32_t sizeBytes)
362{
363 uint32_t eSize = mType->getElementSizeBytes();
364 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
365 ptr += eSize * (x + y * mType->getDimX());
366
367 if (x >= mType->getDimX()) {
368 LOGE("Error Allocation::subElementData X offset %i out of range.", x);
369 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
370 return;
371 }
372
373 if (y >= mType->getDimY()) {
374 LOGE("Error Allocation::subElementData X offset %i out of range.", x);
375 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
376 return;
377 }
378
379 if (cIdx >= mType->getElement()->getFieldCount()) {
380 LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
381 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
382 return;
383 }
384
385 const Element * e = mType->getElement()->getField(cIdx);
386 ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
387
388 if (sizeBytes != e->getSizeBytes()) {
389 LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
390 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
391 return;
392 }
393
394 if (e->getHasReferences()) {
395 e->incRefs(data);
396 e->decRefs(ptr);
397 }
398
399 memcpy(ptr, data, sizeBytes);
400 sendDirty();
401 mUploadDefered = true;
402}
403
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700404void Allocation::addProgramToDirty(const Program *p)
405{
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700406 mToDirtyList.push(p);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700407}
Jason Sams326e0dd2009-05-22 14:03:28 -0700408
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700409void Allocation::removeProgramToDirty(const Program *p)
410{
411 for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
412 if (mToDirtyList[ct] == p) {
413 mToDirtyList.removeAt(ct);
414 return;
415 }
416 }
417 rsAssert(0);
418}
419
Jason Samsc21cf402009-11-17 17:26:46 -0800420void Allocation::dumpLOGV(const char *prefix) const
421{
422 ObjectBase::dumpLOGV(prefix);
423
424 String8 s(prefix);
425 s.append(" type ");
426 if (mType.get()) {
427 mType->dumpLOGV(s.string());
428 }
429
430 LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i",
431 prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead);
432
Jason Sams43999e72009-11-23 15:27:33 -0800433 LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i",
Jason Samsc21cf402009-11-17 17:26:46 -0800434 prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID);
435
Jason Samsc21cf402009-11-17 17:26:46 -0800436}
Jason Sams326e0dd2009-05-22 14:03:28 -0700437
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700438void Allocation::serialize(OStream *stream) const
439{
440 // Need to identify ourselves
441 stream->addU32((uint32_t)getClassId());
442
443 String8 name(getName());
444 stream->addString(&name);
445
446 // First thing we need to serialize is the type object since it will be needed
447 // to initialize the class
448 mType->serialize(stream);
449
450 uint32_t dataSize = mType->getSizeBytes();
451 // Write how much data we are storing
452 stream->addU32(dataSize);
453 // Now write the data
454 stream->addByteArray(mPtr, dataSize);
455}
456
457Allocation *Allocation::createFromStream(Context *rsc, IStream *stream)
458{
459 // First make sure we are reading the correct object
Alex Sakhartchoukb825f672010-06-04 10:06:50 -0700460 RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
461 if(classID != RS_A3D_CLASS_ID_ALLOCATION) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700462 LOGE("allocation loading skipped due to invalid class id\n");
463 return NULL;
464 }
465
466 String8 name;
467 stream->loadString(&name);
468
469 Type *type = Type::createFromStream(rsc, stream);
470 if(!type) {
471 return NULL;
472 }
473 type->compute();
474
475 // Number of bytes we wrote out for this allocation
476 uint32_t dataSize = stream->loadU32();
477 if(dataSize != type->getSizeBytes()) {
478 LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
Jason Sams225afd32010-10-21 14:06:55 -0700479 ObjectBase::checkDelete(type);
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700480 return NULL;
481 }
482
483 Allocation *alloc = new Allocation(rsc, type);
484 alloc->setName(name.string(), name.size());
485
486 // Read in all of our allocation data
Jason Sams5f0c84c2010-08-31 13:50:42 -0700487 alloc->data(rsc, stream->getPtr() + stream->getPos(), dataSize);
Alex Sakhartchouke6d9fbc2010-08-11 10:30:44 -0700488 stream->reset(stream->getPos() + dataSize);
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700489
490 return alloc;
491}
492
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700493void Allocation::sendDirty() const
494{
495 for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
496 mToDirtyList[ct]->forceDirty();
497 }
498}
Jason Sams326e0dd2009-05-22 14:03:28 -0700499
Jason Sams96abf812010-10-05 13:32:49 -0700500void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const
Jason Samse3929c92010-08-09 18:13:33 -0700501{
502 const uint8_t *p = static_cast<const uint8_t *>(ptr);
503 const Element *e = mType->getElement();
504 uint32_t stride = e->getSizeBytes();
505
Jason Sams96abf812010-10-05 13:32:49 -0700506 p += stride * startOff;
Jason Samse3929c92010-08-09 18:13:33 -0700507 while (ct > 0) {
508 e->incRefs(p);
509 ct --;
510 p += stride;
511 }
512}
513
Jason Sams96abf812010-10-05 13:32:49 -0700514void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const
Jason Samse3929c92010-08-09 18:13:33 -0700515{
516 const uint8_t *p = static_cast<const uint8_t *>(ptr);
517 const Element *e = mType->getElement();
518 uint32_t stride = e->getSizeBytes();
519
Jason Sams96abf812010-10-05 13:32:49 -0700520 p += stride * startOff;
Jason Samse3929c92010-08-09 18:13:33 -0700521 while (ct > 0) {
522 e->decRefs(p);
523 ct --;
524 p += stride;
525 }
526}
527
Jason Sams96abf812010-10-05 13:32:49 -0700528void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len)
529{
530}
531
532void Allocation::resize1D(Context *rsc, uint32_t dimX)
533{
534 Type *t = mType->cloneAndResize1D(rsc, dimX);
535
536 uint32_t oldDimX = mType->getDimX();
537 if (dimX == oldDimX) {
538 return;
539 }
540
541 if (dimX < oldDimX) {
542 decRefs(mPtr, oldDimX - dimX, dimX);
543 }
544 mPtr = realloc(mPtr, t->getSizeBytes());
545
546 if (dimX > oldDimX) {
547 const Element *e = mType->getElement();
548 uint32_t stride = e->getSizeBytes();
549 memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
550 }
551 mType.set(t);
552}
553
554void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY)
555{
556 LOGE("not implemented");
557}
558
Jason Sams326e0dd2009-05-22 14:03:28 -0700559/////////////////
Jason Sams565ac362009-06-03 16:04:54 -0700560//
Jason Sams326e0dd2009-05-22 14:03:28 -0700561
562
563namespace android {
564namespace renderscript {
565
Jason Sams7fabe1a2010-02-23 17:44:28 -0800566void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel)
Jason Sams326e0dd2009-05-22 14:03:28 -0700567{
568 Allocation *alloc = static_cast<Allocation *>(va);
Jason Sams7fabe1a2010-02-23 17:44:28 -0800569 alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel);
Jason Sams326e0dd2009-05-22 14:03:28 -0700570}
571
572void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
573{
574 Allocation *alloc = static_cast<Allocation *>(va);
Jason Samscf4c7c92009-12-14 12:57:40 -0800575 alloc->deferedUploadToBufferObject(rsc);
Jason Sams326e0dd2009-05-22 14:03:28 -0700576}
577
Jason Sams565ac362009-06-03 16:04:54 -0700578static void mip565(const Adapter2D &out, const Adapter2D &in)
Jason Sams326e0dd2009-05-22 14:03:28 -0700579{
580 uint32_t w = out.getDimX();
581 uint32_t h = out.getDimY();
582
Jason Samse9f5c532009-07-28 17:20:11 -0700583 for (uint32_t y=0; y < h; y++) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700584 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
585 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
586 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
587
Jason Samse9f5c532009-07-28 17:20:11 -0700588 for (uint32_t x=0; x < w; x++) {
Jason Sams565ac362009-06-03 16:04:54 -0700589 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
590 oPtr ++;
591 i1 += 2;
592 i2 += 2;
593 }
594 }
595}
596
597static void mip8888(const Adapter2D &out, const Adapter2D &in)
598{
599 uint32_t w = out.getDimX();
600 uint32_t h = out.getDimY();
601
Jason Samse9f5c532009-07-28 17:20:11 -0700602 for (uint32_t y=0; y < h; y++) {
Jason Sams565ac362009-06-03 16:04:54 -0700603 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
604 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
605 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
606
Jason Samse9f5c532009-07-28 17:20:11 -0700607 for (uint32_t x=0; x < w; x++) {
Jason Sams565ac362009-06-03 16:04:54 -0700608 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
Jason Sams326e0dd2009-05-22 14:03:28 -0700609 oPtr ++;
610 i1 += 2;
611 i2 += 2;
612 }
613 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700614}
615
Jason Sams2f6d8612010-01-19 17:53:54 -0800616static void mip8(const Adapter2D &out, const Adapter2D &in)
617{
618 uint32_t w = out.getDimX();
619 uint32_t h = out.getDimY();
620
621 for (uint32_t y=0; y < h; y++) {
622 uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
623 const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
624 const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
625
626 for (uint32_t x=0; x < w; x++) {
627 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
628 oPtr ++;
629 i1 += 2;
630 i2 += 2;
631 }
632 }
633}
634
Jason Samse9f5c532009-07-28 17:20:11 -0700635static void mip(const Adapter2D &out, const Adapter2D &in)
636{
637 switch(out.getBaseType()->getElement()->getSizeBits()) {
638 case 32:
639 mip8888(out, in);
640 break;
641 case 16:
642 mip565(out, in);
643 break;
Jason Sams2f6d8612010-01-19 17:53:54 -0800644 case 8:
645 mip8(out, in);
646 break;
Jason Samse9f5c532009-07-28 17:20:11 -0700647
648 }
649
650}
Jason Sams326e0dd2009-05-22 14:03:28 -0700651
Jason Sams6678e9b2009-05-27 14:45:32 -0700652typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
653
654static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
655{
656 memcpy(dst, src, count * 2);
657}
658static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
659{
660 memcpy(dst, src, count);
661}
662static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
663{
664 memcpy(dst, src, count * 4);
665}
666
667
668static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
669{
670 uint16_t *d = static_cast<uint16_t *>(dst);
671 const uint8_t *s = static_cast<const uint8_t *>(src);
672
673 while(count--) {
674 *d = rs888to565(s[0], s[1], s[2]);
675 d++;
676 s+= 3;
677 }
678}
679
680static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
681{
682 uint16_t *d = static_cast<uint16_t *>(dst);
683 const uint8_t *s = static_cast<const uint8_t *>(src);
684
685 while(count--) {
686 *d = rs888to565(s[0], s[1], s[2]);
687 d++;
688 s+= 4;
689 }
690}
691
Jason Samsa57c0a72009-09-04 14:42:41 -0700692static ElementConverter_t pickConverter(const Element *dst, const Element *src)
Jason Sams6678e9b2009-05-27 14:45:32 -0700693{
Jason Samsd01d9702009-12-23 14:35:29 -0800694 GLenum srcGLType = src->getComponent().getGLType();
695 GLenum srcGLFmt = src->getComponent().getGLFormat();
696 GLenum dstGLType = dst->getComponent().getGLType();
697 GLenum dstGLFmt = dst->getComponent().getGLFormat();
Jason Samsa57c0a72009-09-04 14:42:41 -0700698
699 if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
700 switch(dst->getSizeBytes()) {
701 case 4:
702 return elementConverter_cpy_32;
703 case 2:
704 return elementConverter_cpy_16;
705 case 1:
706 return elementConverter_cpy_8;
707 }
Jason Sams6678e9b2009-05-27 14:45:32 -0700708 }
709
Jason Samsa57c0a72009-09-04 14:42:41 -0700710 if (srcGLType == GL_UNSIGNED_BYTE &&
711 srcGLFmt == GL_RGB &&
712 dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
Jason Sams44b28942010-06-22 17:45:34 -0700713 dstGLFmt == GL_RGB) {
Jason Samsa57c0a72009-09-04 14:42:41 -0700714
Jason Sams6678e9b2009-05-27 14:45:32 -0700715 return elementConverter_888_to_565;
716 }
717
Jason Samsa57c0a72009-09-04 14:42:41 -0700718 if (srcGLType == GL_UNSIGNED_BYTE &&
719 srcGLFmt == GL_RGBA &&
720 dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
Jason Sams44b28942010-06-22 17:45:34 -0700721 dstGLFmt == GL_RGB) {
Jason Samsa57c0a72009-09-04 14:42:41 -0700722
Jason Sams6678e9b2009-05-27 14:45:32 -0700723 return elementConverter_8888_to_565;
724 }
725
Jason Samsa57c0a72009-09-04 14:42:41 -0700726 LOGE("pickConverter, unsuported combo, src %p, dst %p", src, dst);
Jason Sams44b28942010-06-22 17:45:34 -0700727 LOGE("pickConverter, srcGLType = %x, srcGLFmt = %x", srcGLType, srcGLFmt);
728 LOGE("pickConverter, dstGLType = %x, dstGLFmt = %x", dstGLType, dstGLFmt);
729 src->dumpLOGV("SRC ");
730 dst->dumpLOGV("DST ");
Jason Sams6678e9b2009-05-27 14:45:32 -0700731 return 0;
732}
733
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700734#ifndef ANDROID_RS_BUILD_FOR_HOST
735
Jason Samsfa84da22010-03-01 15:31:04 -0800736RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype,
737 void *bmp, void *callbackData, RsBitmapCallback_t callback)
738{
739 const Type * type = static_cast<const Type *>(vtype);
740 Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback);
741 alloc->incUserRef();
742 return alloc;
743}
Jason Sams6678e9b2009-05-27 14:45:32 -0700744
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700745void rsi_AllocationUpdateFromBitmap(Context *rsc, RsAllocation va, RsElement _src, const void *data)
746{
747 Allocation *texAlloc = static_cast<Allocation *>(va);
748 const Element *src = static_cast<const Element *>(_src);
749 const Element *dst = texAlloc->getType()->getElement();
750 uint32_t w = texAlloc->getType()->getDimX();
751 uint32_t h = texAlloc->getType()->getDimY();
752 bool genMips = texAlloc->getType()->getDimLOD();
753
754 ElementConverter_t cvt = pickConverter(dst, src);
755 if (cvt) {
756 cvt(texAlloc->getPtr(), data, w * h);
757 if (genMips) {
758 Adapter2D adapt(rsc, texAlloc);
759 Adapter2D adapt2(rsc, texAlloc);
760 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
761 adapt.setLOD(lod);
762 adapt2.setLOD(lod + 1);
763 mip(adapt2, adapt);
764 }
765 }
766 } else {
767 rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
768 }
769}
770
Jason Sams9397e302009-08-27 20:23:34 -0700771void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700772{
773 Allocation *a = static_cast<Allocation *>(va);
Jason Sams5f0c84c2010-08-31 13:50:42 -0700774 a->data(rsc, data, sizeBytes);
Jason Sams326e0dd2009-05-22 14:03:28 -0700775}
776
Jason Sams9397e302009-08-27 20:23:34 -0700777void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700778{
779 Allocation *a = static_cast<Allocation *>(va);
Jason Sams5f0c84c2010-08-31 13:50:42 -0700780 a->subData(rsc, xoff, count, data, sizeBytes);
781}
782
783void rsi_Allocation2DSubElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, const void *data, uint32_t eoff, uint32_t sizeBytes)
784{
785 Allocation *a = static_cast<Allocation *>(va);
786 a->subElementData(rsc, x, y, data, eoff, sizeBytes);
787}
788
789void rsi_Allocation1DSubElementData(Context *rsc, RsAllocation va, uint32_t x, const void *data, uint32_t eoff, uint32_t sizeBytes)
790{
791 Allocation *a = static_cast<Allocation *>(va);
792 a->subElementData(rsc, x, data, eoff, sizeBytes);
Jason Sams326e0dd2009-05-22 14:03:28 -0700793}
794
Jason Sams9397e302009-08-27 20:23:34 -0700795void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
Jason Sams326e0dd2009-05-22 14:03:28 -0700796{
797 Allocation *a = static_cast<Allocation *>(va);
Jason Sams5f0c84c2010-08-31 13:50:42 -0700798 a->subData(rsc, xoff, yoff, w, h, data, sizeBytes);
Jason Sams326e0dd2009-05-22 14:03:28 -0700799}
800
Jason Samse579df42009-08-10 14:55:26 -0700801void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data)
802{
803 Allocation *a = static_cast<Allocation *>(va);
804 a->read(data);
805}
806
Jason Sams96abf812010-10-05 13:32:49 -0700807void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX)
808{
809 Allocation *a = static_cast<Allocation *>(va);
810 a->resize1D(rsc, dimX);
811}
812
813void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY)
814{
815 Allocation *a = static_cast<Allocation *>(va);
816 a->resize2D(rsc, dimX, dimY);
817}
818
Alex Sakhartchoukdc763f32010-10-27 14:10:07 -0700819#endif //ANDROID_RS_BUILD_FOR_HOST
820
821}
822}
823
824const void * rsaAllocationGetType(RsContext con, RsAllocation va)
Alex Sakhartchoukd18c7442010-07-12 15:50:32 -0700825{
826 Allocation *a = static_cast<Allocation *>(va);
827 a->getType()->incUserRef();
828
829 return a->getType();
830}
831
Jason Samsf0c1df42010-10-26 13:09:17 -0700832RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype)
833{
834 Context *rsc = static_cast<Context *>(con);
835 Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype));
836 alloc->incUserRef();
837 return alloc;
838}
839
840RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data)
841{
842 Context *rsc = static_cast<Context *>(con);
843 const Element *src = static_cast<const Element *>(_src);
844 const Element *dst = static_cast<const Element *>(_dst);
845
846 //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
847 RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
848 uint32_t dimValues[] = {w, h, genMips};
849 RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
850
851 RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, type);
852 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
853 if (texAlloc == NULL) {
854 LOGE("Memory allocation failure");
855 return NULL;
856 }
857
858 ElementConverter_t cvt = pickConverter(dst, src);
859 if (cvt) {
860 cvt(texAlloc->getPtr(), data, w * h);
861 if (genMips) {
862 Adapter2D adapt(rsc, texAlloc);
863 Adapter2D adapt2(rsc, texAlloc);
864 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
865 adapt.setLOD(lod);
866 adapt2.setLOD(lod + 1);
867 mip(adapt2, adapt);
868 }
869 }
870 } else {
871 rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
872 }
873
874 return texAlloc;
875}