blob: 23135e21033662666adc8cd50e96424f2d4bd48d [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
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080034Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc) {
Jason Samsfa84da22010-03-01 15:31:04 -080035 init(rsc, type);
36
37 mPtr = malloc(mType->getSizeBytes());
Jason Sams10e5e572010-08-12 12:44:02 -070038 if (mType->getElement()->getHasReferences()) {
39 memset(mPtr, 0, mType->getSizeBytes());
40 }
Jason Samsfa84da22010-03-01 15:31:04 -080041 if (!mPtr) {
42 LOGE("Allocation::Allocation, alloc failure");
43 }
44}
45
46Allocation::Allocation(Context *rsc, const Type *type, void *bmp,
47 void *callbackData, RsBitmapCallback_t callback)
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080048 : ObjectBase(rsc) {
Jason Samsfa84da22010-03-01 15:31:04 -080049 init(rsc, type);
50
51 mPtr = bmp;
52 mUserBitmapCallback = callback;
53 mUserBitmapCallbackData = callbackData;
54}
55
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080056void Allocation::init(Context *rsc, const Type *type) {
Jason Sams326e0dd2009-05-22 14:03:28 -070057 mPtr = NULL;
58
59 mCpuWrite = false;
60 mCpuRead = false;
61 mGpuWrite = false;
62 mGpuRead = false;
63
64 mReadWriteRatio = 0;
65 mUpdateSize = 0;
66
67 mIsTexture = false;
68 mTextureID = 0;
Jason Sams326e0dd2009-05-22 14:03:28 -070069 mIsVertexBuffer = false;
70 mBufferID = 0;
Jason Samscf4c7c92009-12-14 12:57:40 -080071 mUploadDefered = false;
Jason Sams326e0dd2009-05-22 14:03:28 -070072
Jason Samsfa84da22010-03-01 15:31:04 -080073 mUserBitmapCallback = NULL;
74 mUserBitmapCallbackData = NULL;
75
Jason Sams326e0dd2009-05-22 14:03:28 -070076 mType.set(type);
Jason Samse5ffb872009-08-09 17:01:55 -070077 rsAssert(type);
Jason Samsfa84da22010-03-01 15:31:04 -080078
79 mPtr = NULL;
Jason Sams326e0dd2009-05-22 14:03:28 -070080}
81
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080082Allocation::~Allocation() {
Jason Samsfa84da22010-03-01 15:31:04 -080083 if (mUserBitmapCallback != NULL) {
84 mUserBitmapCallback(mUserBitmapCallbackData);
85 } else {
86 free(mPtr);
87 }
Jason Samsbf3c14e2009-11-02 14:25:10 -080088 mPtr = NULL;
Jason Samse402ed32009-11-03 11:25:42 -080089
90 if (mBufferID) {
91 // Causes a SW crash....
92 //LOGV(" mBufferID %i", mBufferID);
93 //glDeleteBuffers(1, &mBufferID);
94 //mBufferID = 0;
95 }
96 if (mTextureID) {
97 glDeleteTextures(1, &mTextureID);
98 mTextureID = 0;
99 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700100}
101
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800102void Allocation::setCpuWritable(bool) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700103}
104
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800105void Allocation::setGpuWritable(bool) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700106}
107
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800108void Allocation::setCpuReadable(bool) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700109}
110
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800111void Allocation::setGpuReadable(bool) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700112}
113
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800114bool Allocation::fixAllocation() {
Jason Sams326e0dd2009-05-22 14:03:28 -0700115 return false;
116}
117
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800118void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset) {
Jason Samscf4c7c92009-12-14 12:57:40 -0800119 rsAssert(lodOffset < mType->getLODCount());
120 mIsTexture = true;
121 mTextureLOD = lodOffset;
122 mUploadDefered = true;
Jason Sams7fabe1a2010-02-23 17:44:28 -0800123 mTextureGenMipmap = !mType->getDimLOD() && genMipmap;
Jason Samscf4c7c92009-12-14 12:57:40 -0800124}
125
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800126void Allocation::uploadToTexture(const Context *rsc) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700127 //rsAssert(!mTextureId);
Jason Samscf4c7c92009-12-14 12:57:40 -0800128
129 mIsTexture = true;
130 if (!rsc->checkDriver()) {
131 mUploadDefered = true;
132 return;
133 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700134
Jason Samsd01d9702009-12-23 14:35:29 -0800135 GLenum type = mType->getElement()->getComponent().getGLType();
136 GLenum format = mType->getElement()->getComponent().getGLFormat();
Jason Sams565ac362009-06-03 16:04:54 -0700137
138 if (!type || !format) {
139 return;
140 }
141
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700142 bool isFirstUpload = false;
143
Jason Sams326e0dd2009-05-22 14:03:28 -0700144 if (!mTextureID) {
145 glGenTextures(1, &mTextureID);
Jason Sams13e26342009-11-24 12:26:35 -0800146
147 if (!mTextureID) {
148 // This should not happen, however, its likely the cause of the
149 // white sqare bug.
150 // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
151 LOGE("Upload to texture failed to gen mTextureID");
152 rsc->dumpDebug();
Jason Samscf4c7c92009-12-14 12:57:40 -0800153 mUploadDefered = true;
154 return;
Jason Sams13e26342009-11-24 12:26:35 -0800155 }
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700156 isFirstUpload = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700157 }
158 glBindTexture(GL_TEXTURE_2D, mTextureID);
Jason Sams5f0b4e12009-11-05 12:44:58 -0800159 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Jason Sams326e0dd2009-05-22 14:03:28 -0700160
Jason Samse514b452009-09-25 14:51:22 -0700161 Adapter2D adapt(getContext(), this);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800162 for (uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
Jason Samscf4c7c92009-12-14 12:57:40 -0800163 adapt.setLOD(lod+mTextureLOD);
Jason Sams326e0dd2009-05-22 14:03:28 -0700164
165 uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800166 if (isFirstUpload) {
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700167 glTexImage2D(GL_TEXTURE_2D, lod, format,
168 adapt.getDimX(), adapt.getDimY(),
169 0, format, type, ptr);
170 } else {
171 glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
172 adapt.getDimX(), adapt.getDimY(),
173 format, type, ptr);
174 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700175 }
Jason Sams7fabe1a2010-02-23 17:44:28 -0800176 if (mTextureGenMipmap) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700177#ifndef ANDROID_RS_BUILD_FOR_HOST
Jason Sams7fabe1a2010-02-23 17:44:28 -0800178 glGenerateMipmap(GL_TEXTURE_2D);
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700179#endif //ANDROID_RS_BUILD_FOR_HOST
Jason Sams7fabe1a2010-02-23 17:44:28 -0800180 }
181
Jason Samsc1ed5892010-03-10 17:30:41 -0800182 rsc->checkError("Allocation::uploadToTexture");
Jason Sams326e0dd2009-05-22 14:03:28 -0700183}
184
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800185void Allocation::deferedUploadToBufferObject(const Context *rsc) {
Jason Samscf4c7c92009-12-14 12:57:40 -0800186 mIsVertexBuffer = true;
187 mUploadDefered = true;
188}
189
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800190void Allocation::uploadToBufferObject(const Context *rsc) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700191 rsAssert(!mType->getDimY());
192 rsAssert(!mType->getDimZ());
193
Jason Samscf4c7c92009-12-14 12:57:40 -0800194 mIsVertexBuffer = true;
195 if (!rsc->checkDriver()) {
196 mUploadDefered = true;
197 return;
198 }
199
Jason Sams326e0dd2009-05-22 14:03:28 -0700200 if (!mBufferID) {
201 glGenBuffers(1, &mBufferID);
202 }
Jason Samscf4c7c92009-12-14 12:57:40 -0800203 if (!mBufferID) {
204 LOGE("Upload to buffer object failed");
205 mUploadDefered = true;
206 return;
207 }
208
Jason Sams326e0dd2009-05-22 14:03:28 -0700209 glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
210 glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
211 glBindBuffer(GL_ARRAY_BUFFER, 0);
Jason Samsc1ed5892010-03-10 17:30:41 -0800212 rsc->checkError("Allocation::uploadToBufferObject");
Jason Sams326e0dd2009-05-22 14:03:28 -0700213}
214
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800215void Allocation::uploadCheck(const Context *rsc) {
Jason Samscf4c7c92009-12-14 12:57:40 -0800216 if (mUploadDefered) {
217 mUploadDefered = false;
218 if (mIsVertexBuffer) {
219 uploadToBufferObject(rsc);
220 }
221 if (mIsTexture) {
222 uploadToTexture(rsc);
223 }
224 }
225}
226
Jason Samse5ffb872009-08-09 17:01:55 -0700227
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800228void Allocation::data(Context *rsc, const void *data, uint32_t sizeBytes) {
Jason Sams9397e302009-08-27 20:23:34 -0700229 uint32_t size = mType->getSizeBytes();
230 if (size != sizeBytes) {
231 LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
232 return;
233 }
Jason Samse3929c92010-08-09 18:13:33 -0700234
235 if (mType->getElement()->getHasReferences()) {
236 incRefs(data, sizeBytes / mType->getElement()->getSizeBytes());
237 decRefs(mPtr, sizeBytes / mType->getElement()->getSizeBytes());
238 }
239
Jason Sams9397e302009-08-27 20:23:34 -0700240 memcpy(mPtr, data, size);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700241 sendDirty();
Jason Samscf4c7c92009-12-14 12:57:40 -0800242 mUploadDefered = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700243}
244
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800245void Allocation::read(void *data) {
Jason Samse579df42009-08-10 14:55:26 -0700246 memcpy(data, mPtr, mType->getSizeBytes());
247}
248
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800249void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700250 uint32_t eSize = mType->getElementSizeBytes();
251 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
252 ptr += eSize * xoff;
Jason Sams9397e302009-08-27 20:23:34 -0700253 uint32_t size = count * eSize;
254
255 if (size != sizeBytes) {
256 LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
Jason Samse12c1c52009-09-27 17:50:38 -0700257 mType->dumpLOGV("type info");
Jason Sams9397e302009-08-27 20:23:34 -0700258 return;
259 }
Jason Samse3929c92010-08-09 18:13:33 -0700260
261 if (mType->getElement()->getHasReferences()) {
262 incRefs(data, count);
263 decRefs(ptr, count);
264 }
265
Jason Sams9397e302009-08-27 20:23:34 -0700266 memcpy(ptr, data, size);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700267 sendDirty();
Jason Samscf4c7c92009-12-14 12:57:40 -0800268 mUploadDefered = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700269}
270
Jason Sams5f0c84c2010-08-31 13:50:42 -0700271void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800272 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700273 uint32_t eSize = mType->getElementSizeBytes();
274 uint32_t lineSize = eSize * w;
275 uint32_t destW = mType->getDimX();
276
277 const uint8_t *src = static_cast<const uint8_t *>(data);
278 uint8_t *dst = static_cast<uint8_t *>(mPtr);
279 dst += eSize * (xoff + yoff * destW);
Jason Sams9397e302009-08-27 20:23:34 -0700280
281 if ((lineSize * eSize * h) != sizeBytes) {
282 rsAssert(!"Allocation::subData called with mismatched size");
283 return;
284 }
285
Jason Sams326e0dd2009-05-22 14:03:28 -0700286 for (uint32_t line=yoff; line < (yoff+h); line++) {
Jason Samse3929c92010-08-09 18:13:33 -0700287 if (mType->getElement()->getHasReferences()) {
288 incRefs(src, w);
289 decRefs(dst, w);
290 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700291 memcpy(dst, src, lineSize);
292 src += lineSize;
293 dst += destW * eSize;
294 }
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700295 sendDirty();
Jason Samscf4c7c92009-12-14 12:57:40 -0800296 mUploadDefered = true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700297}
298
Jason Sams5f0c84c2010-08-31 13:50:42 -0700299void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800300 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700301}
302
Jason Sams5f0c84c2010-08-31 13:50:42 -0700303void Allocation::subElementData(Context *rsc, uint32_t x, const void *data,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800304 uint32_t cIdx, uint32_t sizeBytes) {
Jason Sams5f0c84c2010-08-31 13:50:42 -0700305 uint32_t eSize = mType->getElementSizeBytes();
306 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
307 ptr += eSize * x;
308
309 if (cIdx >= mType->getElement()->getFieldCount()) {
310 LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
311 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
312 return;
313 }
314
315 if (x >= mType->getDimX()) {
316 LOGE("Error Allocation::subElementData X offset %i out of range.", x);
317 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
318 return;
319 }
320
321 const Element * e = mType->getElement()->getField(cIdx);
322 ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
323
324 if (sizeBytes != e->getSizeBytes()) {
325 LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
326 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
327 return;
328 }
329
330 if (e->getHasReferences()) {
331 e->incRefs(data);
332 e->decRefs(ptr);
333 }
334
335 memcpy(ptr, data, sizeBytes);
336 sendDirty();
337 mUploadDefered = true;
338}
339
340void Allocation::subElementData(Context *rsc, uint32_t x, uint32_t y,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800341 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
Jason Sams5f0c84c2010-08-31 13:50:42 -0700342 uint32_t eSize = mType->getElementSizeBytes();
343 uint8_t * ptr = static_cast<uint8_t *>(mPtr);
344 ptr += eSize * (x + y * mType->getDimX());
345
346 if (x >= mType->getDimX()) {
347 LOGE("Error Allocation::subElementData X offset %i out of range.", x);
348 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
349 return;
350 }
351
352 if (y >= mType->getDimY()) {
353 LOGE("Error Allocation::subElementData X offset %i out of range.", x);
354 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
355 return;
356 }
357
358 if (cIdx >= mType->getElement()->getFieldCount()) {
359 LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
360 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
361 return;
362 }
363
364 const Element * e = mType->getElement()->getField(cIdx);
365 ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
366
367 if (sizeBytes != e->getSizeBytes()) {
368 LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
369 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
370 return;
371 }
372
373 if (e->getHasReferences()) {
374 e->incRefs(data);
375 e->decRefs(ptr);
376 }
377
378 memcpy(ptr, data, sizeBytes);
379 sendDirty();
380 mUploadDefered = true;
381}
382
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800383void Allocation::addProgramToDirty(const Program *p) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700384 mToDirtyList.push(p);
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700385}
Jason Sams326e0dd2009-05-22 14:03:28 -0700386
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800387void Allocation::removeProgramToDirty(const Program *p) {
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700388 for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
389 if (mToDirtyList[ct] == p) {
390 mToDirtyList.removeAt(ct);
391 return;
392 }
393 }
394 rsAssert(0);
395}
396
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800397void Allocation::dumpLOGV(const char *prefix) const {
Jason Samsc21cf402009-11-17 17:26:46 -0800398 ObjectBase::dumpLOGV(prefix);
399
400 String8 s(prefix);
401 s.append(" type ");
402 if (mType.get()) {
403 mType->dumpLOGV(s.string());
404 }
405
406 LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i",
407 prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead);
408
Jason Sams43999e72009-11-23 15:27:33 -0800409 LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i",
Jason Samsc21cf402009-11-17 17:26:46 -0800410 prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID);
Jason Samsc21cf402009-11-17 17:26:46 -0800411}
Jason Sams326e0dd2009-05-22 14:03:28 -0700412
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800413void Allocation::serialize(OStream *stream) const {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700414 // Need to identify ourselves
415 stream->addU32((uint32_t)getClassId());
416
417 String8 name(getName());
418 stream->addString(&name);
419
420 // First thing we need to serialize is the type object since it will be needed
421 // to initialize the class
422 mType->serialize(stream);
423
424 uint32_t dataSize = mType->getSizeBytes();
425 // Write how much data we are storing
426 stream->addU32(dataSize);
427 // Now write the data
428 stream->addByteArray(mPtr, dataSize);
429}
430
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800431Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700432 // First make sure we are reading the correct object
Alex Sakhartchoukb825f672010-06-04 10:06:50 -0700433 RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800434 if (classID != RS_A3D_CLASS_ID_ALLOCATION) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700435 LOGE("allocation loading skipped due to invalid class id\n");
436 return NULL;
437 }
438
439 String8 name;
440 stream->loadString(&name);
441
442 Type *type = Type::createFromStream(rsc, stream);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800443 if (!type) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700444 return NULL;
445 }
446 type->compute();
447
448 // Number of bytes we wrote out for this allocation
449 uint32_t dataSize = stream->loadU32();
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800450 if (dataSize != type->getSizeBytes()) {
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700451 LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
Jason Sams225afd32010-10-21 14:06:55 -0700452 ObjectBase::checkDelete(type);
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700453 return NULL;
454 }
455
456 Allocation *alloc = new Allocation(rsc, type);
457 alloc->setName(name.string(), name.size());
458
459 // Read in all of our allocation data
Jason Sams5f0c84c2010-08-31 13:50:42 -0700460 alloc->data(rsc, stream->getPtr() + stream->getPos(), dataSize);
Alex Sakhartchouke6d9fbc2010-08-11 10:30:44 -0700461 stream->reset(stream->getPos() + dataSize);
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700462
463 return alloc;
464}
465
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800466void Allocation::sendDirty() const {
Jason Sams5c3e3bc2009-10-26 15:19:28 -0700467 for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
468 mToDirtyList[ct]->forceDirty();
469 }
470}
Jason Sams326e0dd2009-05-22 14:03:28 -0700471
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800472void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
Jason Samse3929c92010-08-09 18:13:33 -0700473 const uint8_t *p = static_cast<const uint8_t *>(ptr);
474 const Element *e = mType->getElement();
475 uint32_t stride = e->getSizeBytes();
476
Jason Sams96abf812010-10-05 13:32:49 -0700477 p += stride * startOff;
Jason Samse3929c92010-08-09 18:13:33 -0700478 while (ct > 0) {
479 e->incRefs(p);
480 ct --;
481 p += stride;
482 }
483}
484
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800485void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
Jason Samse3929c92010-08-09 18:13:33 -0700486 const uint8_t *p = static_cast<const uint8_t *>(ptr);
487 const Element *e = mType->getElement();
488 uint32_t stride = e->getSizeBytes();
489
Jason Sams96abf812010-10-05 13:32:49 -0700490 p += stride * startOff;
Jason Samse3929c92010-08-09 18:13:33 -0700491 while (ct > 0) {
492 e->decRefs(p);
493 ct --;
494 p += stride;
495 }
496}
497
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800498void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) {
Jason Sams96abf812010-10-05 13:32:49 -0700499}
500
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800501void Allocation::resize1D(Context *rsc, uint32_t dimX) {
Jason Sams96abf812010-10-05 13:32:49 -0700502 Type *t = mType->cloneAndResize1D(rsc, dimX);
503
504 uint32_t oldDimX = mType->getDimX();
505 if (dimX == oldDimX) {
506 return;
507 }
508
509 if (dimX < oldDimX) {
510 decRefs(mPtr, oldDimX - dimX, dimX);
511 }
512 mPtr = realloc(mPtr, t->getSizeBytes());
513
514 if (dimX > oldDimX) {
515 const Element *e = mType->getElement();
516 uint32_t stride = e->getSizeBytes();
517 memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
518 }
519 mType.set(t);
520}
521
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800522void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
Jason Sams96abf812010-10-05 13:32:49 -0700523 LOGE("not implemented");
524}
525
Jason Sams326e0dd2009-05-22 14:03:28 -0700526/////////////////
Jason Sams565ac362009-06-03 16:04:54 -0700527//
Jason Sams326e0dd2009-05-22 14:03:28 -0700528
529
530namespace android {
531namespace renderscript {
532
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800533void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700534 Allocation *alloc = static_cast<Allocation *>(va);
Jason Sams7fabe1a2010-02-23 17:44:28 -0800535 alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel);
Jason Sams326e0dd2009-05-22 14:03:28 -0700536}
537
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800538void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700539 Allocation *alloc = static_cast<Allocation *>(va);
Jason Samscf4c7c92009-12-14 12:57:40 -0800540 alloc->deferedUploadToBufferObject(rsc);
Jason Sams326e0dd2009-05-22 14:03:28 -0700541}
542
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800543static void mip565(const Adapter2D &out, const Adapter2D &in) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700544 uint32_t w = out.getDimX();
545 uint32_t h = out.getDimY();
546
Jason Samse9f5c532009-07-28 17:20:11 -0700547 for (uint32_t y=0; y < h; y++) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700548 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
549 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
550 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
551
Jason Samse9f5c532009-07-28 17:20:11 -0700552 for (uint32_t x=0; x < w; x++) {
Jason Sams565ac362009-06-03 16:04:54 -0700553 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
554 oPtr ++;
555 i1 += 2;
556 i2 += 2;
557 }
558 }
559}
560
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800561static void mip8888(const Adapter2D &out, const Adapter2D &in) {
Jason Sams565ac362009-06-03 16:04:54 -0700562 uint32_t w = out.getDimX();
563 uint32_t h = out.getDimY();
564
Jason Samse9f5c532009-07-28 17:20:11 -0700565 for (uint32_t y=0; y < h; y++) {
Jason Sams565ac362009-06-03 16:04:54 -0700566 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
567 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
568 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
569
Jason Samse9f5c532009-07-28 17:20:11 -0700570 for (uint32_t x=0; x < w; x++) {
Jason Sams565ac362009-06-03 16:04:54 -0700571 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
Jason Sams326e0dd2009-05-22 14:03:28 -0700572 oPtr ++;
573 i1 += 2;
574 i2 += 2;
575 }
576 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700577}
578
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800579static void mip8(const Adapter2D &out, const Adapter2D &in) {
Jason Sams2f6d8612010-01-19 17:53:54 -0800580 uint32_t w = out.getDimX();
581 uint32_t h = out.getDimY();
582
583 for (uint32_t y=0; y < h; y++) {
584 uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
585 const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
586 const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
587
588 for (uint32_t x=0; x < w; x++) {
589 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
590 oPtr ++;
591 i1 += 2;
592 i2 += 2;
593 }
594 }
595}
596
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800597static void mip(const Adapter2D &out, const Adapter2D &in) {
598 switch (out.getBaseType()->getElement()->getSizeBits()) {
Jason Samse9f5c532009-07-28 17:20:11 -0700599 case 32:
600 mip8888(out, in);
601 break;
602 case 16:
603 mip565(out, in);
604 break;
Jason Sams2f6d8612010-01-19 17:53:54 -0800605 case 8:
606 mip8(out, in);
607 break;
Jason Samse9f5c532009-07-28 17:20:11 -0700608 }
Jason Samse9f5c532009-07-28 17:20:11 -0700609}
Jason Sams326e0dd2009-05-22 14:03:28 -0700610
Jason Sams6678e9b2009-05-27 14:45:32 -0700611typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
612
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800613static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700614 memcpy(dst, src, count * 2);
615}
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800616static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700617 memcpy(dst, src, count);
618}
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800619static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700620 memcpy(dst, src, count * 4);
621}
622
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800623static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700624 uint16_t *d = static_cast<uint16_t *>(dst);
625 const uint8_t *s = static_cast<const uint8_t *>(src);
626
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800627 while (count--) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700628 *d = rs888to565(s[0], s[1], s[2]);
629 d++;
630 s+= 3;
631 }
632}
633
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800634static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700635 uint16_t *d = static_cast<uint16_t *>(dst);
636 const uint8_t *s = static_cast<const uint8_t *>(src);
637
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800638 while (count--) {
Jason Sams6678e9b2009-05-27 14:45:32 -0700639 *d = rs888to565(s[0], s[1], s[2]);
640 d++;
641 s+= 4;
642 }
643}
644
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800645static ElementConverter_t pickConverter(const Element *dst, const Element *src) {
Jason Samsd01d9702009-12-23 14:35:29 -0800646 GLenum srcGLType = src->getComponent().getGLType();
647 GLenum srcGLFmt = src->getComponent().getGLFormat();
648 GLenum dstGLType = dst->getComponent().getGLType();
649 GLenum dstGLFmt = dst->getComponent().getGLFormat();
Jason Samsa57c0a72009-09-04 14:42:41 -0700650
651 if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800652 switch (dst->getSizeBytes()) {
Jason Samsa57c0a72009-09-04 14:42:41 -0700653 case 4:
654 return elementConverter_cpy_32;
655 case 2:
656 return elementConverter_cpy_16;
657 case 1:
658 return elementConverter_cpy_8;
659 }
Jason Sams6678e9b2009-05-27 14:45:32 -0700660 }
661
Jason Samsa57c0a72009-09-04 14:42:41 -0700662 if (srcGLType == GL_UNSIGNED_BYTE &&
663 srcGLFmt == GL_RGB &&
664 dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
Jason Sams44b28942010-06-22 17:45:34 -0700665 dstGLFmt == GL_RGB) {
Jason Samsa57c0a72009-09-04 14:42:41 -0700666
Jason Sams6678e9b2009-05-27 14:45:32 -0700667 return elementConverter_888_to_565;
668 }
669
Jason Samsa57c0a72009-09-04 14:42:41 -0700670 if (srcGLType == GL_UNSIGNED_BYTE &&
671 srcGLFmt == GL_RGBA &&
672 dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
Jason Sams44b28942010-06-22 17:45:34 -0700673 dstGLFmt == GL_RGB) {
Jason Samsa57c0a72009-09-04 14:42:41 -0700674
Jason Sams6678e9b2009-05-27 14:45:32 -0700675 return elementConverter_8888_to_565;
676 }
677
Jason Samsa57c0a72009-09-04 14:42:41 -0700678 LOGE("pickConverter, unsuported combo, src %p, dst %p", src, dst);
Jason Sams44b28942010-06-22 17:45:34 -0700679 LOGE("pickConverter, srcGLType = %x, srcGLFmt = %x", srcGLType, srcGLFmt);
680 LOGE("pickConverter, dstGLType = %x, dstGLFmt = %x", dstGLType, dstGLFmt);
681 src->dumpLOGV("SRC ");
682 dst->dumpLOGV("DST ");
Jason Sams6678e9b2009-05-27 14:45:32 -0700683 return 0;
684}
685
Alex Sakhartchoukfb6b6142010-05-21 12:53:13 -0700686#ifndef ANDROID_RS_BUILD_FOR_HOST
687
Jason Samsfa84da22010-03-01 15:31:04 -0800688RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800689 void *bmp, void *callbackData,
690 RsBitmapCallback_t callback) {
Jason Samsfa84da22010-03-01 15:31:04 -0800691 const Type * type = static_cast<const Type *>(vtype);
692 Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback);
693 alloc->incUserRef();
694 return alloc;
695}
Jason Sams6678e9b2009-05-27 14:45:32 -0700696
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800697void rsi_AllocationUpdateFromBitmap(Context *rsc, RsAllocation va,
698 RsElement _src, const void *data) {
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700699 Allocation *texAlloc = static_cast<Allocation *>(va);
700 const Element *src = static_cast<const Element *>(_src);
701 const Element *dst = texAlloc->getType()->getElement();
702 uint32_t w = texAlloc->getType()->getDimX();
703 uint32_t h = texAlloc->getType()->getDimY();
704 bool genMips = texAlloc->getType()->getDimLOD();
705
706 ElementConverter_t cvt = pickConverter(dst, src);
707 if (cvt) {
708 cvt(texAlloc->getPtr(), data, w * h);
709 if (genMips) {
710 Adapter2D adapt(rsc, texAlloc);
711 Adapter2D adapt2(rsc, texAlloc);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800712 for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
Alex Sakhartchouk39f2ef62010-10-11 12:35:15 -0700713 adapt.setLOD(lod);
714 adapt2.setLOD(lod + 1);
715 mip(adapt2, adapt);
716 }
717 }
718 } else {
719 rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
720 }
721}
722
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800723void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700724 Allocation *a = static_cast<Allocation *>(va);
Jason Sams5f0c84c2010-08-31 13:50:42 -0700725 a->data(rsc, data, sizeBytes);
Jason Sams326e0dd2009-05-22 14:03:28 -0700726}
727
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800728void 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 -0700729 Allocation *a = static_cast<Allocation *>(va);
Jason Sams5f0c84c2010-08-31 13:50:42 -0700730 a->subData(rsc, xoff, count, data, sizeBytes);
731}
732
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800733void rsi_Allocation2DSubElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, const void *data, uint32_t eoff, uint32_t sizeBytes) {
Jason Sams5f0c84c2010-08-31 13:50:42 -0700734 Allocation *a = static_cast<Allocation *>(va);
735 a->subElementData(rsc, x, y, data, eoff, sizeBytes);
736}
737
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800738void rsi_Allocation1DSubElementData(Context *rsc, RsAllocation va, uint32_t x, const void *data, uint32_t eoff, uint32_t sizeBytes) {
Jason Sams5f0c84c2010-08-31 13:50:42 -0700739 Allocation *a = static_cast<Allocation *>(va);
740 a->subElementData(rsc, x, data, eoff, sizeBytes);
Jason Sams326e0dd2009-05-22 14:03:28 -0700741}
742
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800743void 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 -0700744 Allocation *a = static_cast<Allocation *>(va);
Jason Sams5f0c84c2010-08-31 13:50:42 -0700745 a->subData(rsc, xoff, yoff, w, h, data, sizeBytes);
Jason Sams326e0dd2009-05-22 14:03:28 -0700746}
747
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800748void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) {
Jason Samse579df42009-08-10 14:55:26 -0700749 Allocation *a = static_cast<Allocation *>(va);
750 a->read(data);
751}
752
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800753void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) {
Jason Sams96abf812010-10-05 13:32:49 -0700754 Allocation *a = static_cast<Allocation *>(va);
755 a->resize1D(rsc, dimX);
756}
757
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800758void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) {
Jason Sams96abf812010-10-05 13:32:49 -0700759 Allocation *a = static_cast<Allocation *>(va);
760 a->resize2D(rsc, dimX, dimY);
761}
762
Alex Sakhartchoukdc763f32010-10-27 14:10:07 -0700763#endif //ANDROID_RS_BUILD_FOR_HOST
764
765}
766}
767
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800768const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
Alex Sakhartchoukd18c7442010-07-12 15:50:32 -0700769 Allocation *a = static_cast<Allocation *>(va);
770 a->getType()->incUserRef();
771
772 return a->getType();
773}
774
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800775RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype) {
Jason Samsf0c1df42010-10-26 13:09:17 -0700776 Context *rsc = static_cast<Context *>(con);
777 Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype));
778 alloc->incUserRef();
779 return alloc;
780}
781
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800782RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) {
Jason Samsf0c1df42010-10-26 13:09:17 -0700783 Context *rsc = static_cast<Context *>(con);
784 const Element *src = static_cast<const Element *>(_src);
785 const Element *dst = static_cast<const Element *>(_dst);
786
787 //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
788 RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
789 uint32_t dimValues[] = {w, h, genMips};
790 RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
791
792 RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, type);
793 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
794 if (texAlloc == NULL) {
795 LOGE("Memory allocation failure");
796 return NULL;
797 }
798
799 ElementConverter_t cvt = pickConverter(dst, src);
800 if (cvt) {
801 cvt(texAlloc->getPtr(), data, w * h);
802 if (genMips) {
803 Adapter2D adapt(rsc, texAlloc);
804 Adapter2D adapt2(rsc, texAlloc);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800805 for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
Jason Samsf0c1df42010-10-26 13:09:17 -0700806 adapt.setLOD(lod);
807 adapt2.setLOD(lod + 1);
808 mip(adapt2, adapt);
809 }
810 }
811 } else {
812 rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
Jason Samsb60d7572010-11-09 17:11:40 -0800813 delete texAlloc;
814 return NULL;
Jason Samsf0c1df42010-10-26 13:09:17 -0700815 }
816
817 return texAlloc;
818}