1 /*
2 * Copyright (C) 2013 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 "rsdCore.h"
18 #include "rsdAllocation.h"
19
20 #include "rsAllocation.h"
21
22 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
23 #include "system/window.h"
24 #include "ui/Rect.h"
25 #include "ui/GraphicBufferMapper.h"
26 #endif
27
28 #ifdef RS_COMPATIBILITY_LIB
29 #include "rsCompatibilityLib.h"
30 #else
31 #include "rsdFrameBufferObj.h"
32 #include "gui/GLConsumer.h"
33 #include "gui/CpuConsumer.h"
34 #include "gui/Surface.h"
35 #include "hardware/gralloc.h"
36
37 #include <GLES/gl.h>
38 #include <GLES2/gl2.h>
39 #include <GLES/glext.h>
40 #endif
41
42 #ifdef RS_SERVER
43 // server requires malloc.h for memalign
44 #include <malloc.h>
45 #endif
46
47 using namespace android;
48 using namespace android::renderscript;
49
50 #ifndef RS_COMPATIBILITY_LIB
51 const static GLenum gFaceOrder[] = {
52 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
53 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
54 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
55 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
56 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
57 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
58 };
59
rsdTypeToGLType(RsDataType t)60 GLenum rsdTypeToGLType(RsDataType t) {
61 switch (t) {
62 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5;
63 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1;
64 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4;
65
66 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT;
67 case RS_TYPE_FLOAT_32: return GL_FLOAT;
68 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE;
69 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT;
70 case RS_TYPE_SIGNED_8: return GL_BYTE;
71 case RS_TYPE_SIGNED_16: return GL_SHORT;
72 default: break;
73 }
74 return 0;
75 }
76
rsdKindToGLFormat(RsDataKind k)77 GLenum rsdKindToGLFormat(RsDataKind k) {
78 switch (k) {
79 case RS_KIND_PIXEL_L: return GL_LUMINANCE;
80 case RS_KIND_PIXEL_A: return GL_ALPHA;
81 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
82 case RS_KIND_PIXEL_RGB: return GL_RGB;
83 case RS_KIND_PIXEL_RGBA: return GL_RGBA;
84 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
85 default: break;
86 }
87 return 0;
88 }
89 #endif
90
GetOffsetPtr(const android::renderscript::Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t lod,RsAllocationCubemapFace face)91 uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
92 uint32_t xoff, uint32_t yoff, uint32_t zoff,
93 uint32_t lod, RsAllocationCubemapFace face) {
94 uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
95 ptr += face * alloc->mHal.drvState.faceOffset;
96 ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * alloc->mHal.drvState.lod[lod].stride;
97 ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
98 ptr += xoff * alloc->mHal.state.elementSizeBytes;
99 return ptr;
100 }
101
102
Update2DTexture(const Context * rsc,const Allocation * alloc,const void * ptr,uint32_t xoff,uint32_t yoff,uint32_t lod,RsAllocationCubemapFace face,uint32_t w,uint32_t h)103 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
104 uint32_t xoff, uint32_t yoff, uint32_t lod,
105 RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
106 #ifndef RS_COMPATIBILITY_LIB
107 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
108
109 rsAssert(drv->textureID);
110 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
111 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
112 GLenum t = GL_TEXTURE_2D;
113 if (alloc->mHal.state.hasFaces) {
114 t = gFaceOrder[face];
115 }
116 RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
117 #endif
118 }
119
120
121 #ifndef RS_COMPATIBILITY_LIB
Upload2DTexture(const Context * rsc,const Allocation * alloc,bool isFirstUpload)122 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
123 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
124
125 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
126 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
127
128 uint32_t faceCount = 1;
129 if (alloc->mHal.state.hasFaces) {
130 faceCount = 6;
131 }
132
133 rsdGLCheckError(rsc, "Upload2DTexture 1 ");
134 for (uint32_t face = 0; face < faceCount; face ++) {
135 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
136 const uint8_t *p = GetOffsetPtr(alloc, 0, 0, 0, lod, (RsAllocationCubemapFace)face);
137
138 GLenum t = GL_TEXTURE_2D;
139 if (alloc->mHal.state.hasFaces) {
140 t = gFaceOrder[face];
141 }
142
143 if (isFirstUpload) {
144 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat,
145 alloc->mHal.state.type->getLODDimX(lod),
146 alloc->mHal.state.type->getLODDimY(lod),
147 0, drv->glFormat, drv->glType, p);
148 } else {
149 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0,
150 alloc->mHal.state.type->getLODDimX(lod),
151 alloc->mHal.state.type->getLODDimY(lod),
152 drv->glFormat, drv->glType, p);
153 }
154 }
155 }
156
157 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
158 RSD_CALL_GL(glGenerateMipmap, drv->glTarget);
159 }
160 rsdGLCheckError(rsc, "Upload2DTexture");
161 }
162 #endif
163
UploadToTexture(const Context * rsc,const Allocation * alloc)164 static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
165 #ifndef RS_COMPATIBILITY_LIB
166 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
167
168 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
169 if (!drv->textureID) {
170 RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
171 }
172 return;
173 }
174
175 if (!drv->glType || !drv->glFormat) {
176 return;
177 }
178
179 if (!alloc->mHal.drvState.lod[0].mallocPtr) {
180 return;
181 }
182
183 bool isFirstUpload = false;
184
185 if (!drv->textureID) {
186 RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
187 isFirstUpload = true;
188 }
189
190 Upload2DTexture(rsc, alloc, isFirstUpload);
191
192 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
193 if (alloc->mHal.drvState.lod[0].mallocPtr) {
194 free(alloc->mHal.drvState.lod[0].mallocPtr);
195 alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
196 }
197 }
198 rsdGLCheckError(rsc, "UploadToTexture");
199 #endif
200 }
201
AllocateRenderTarget(const Context * rsc,const Allocation * alloc)202 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
203 #ifndef RS_COMPATIBILITY_LIB
204 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
205
206 if (!drv->glFormat) {
207 return;
208 }
209
210 if (!drv->renderTargetID) {
211 RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID);
212
213 if (!drv->renderTargetID) {
214 // This should generally not happen
215 ALOGE("allocateRenderTarget failed to gen mRenderTargetID");
216 rsc->dumpDebug();
217 return;
218 }
219 RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID);
220 RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat,
221 alloc->mHal.drvState.lod[0].dimX, alloc->mHal.drvState.lod[0].dimY);
222 }
223 rsdGLCheckError(rsc, "AllocateRenderTarget");
224 #endif
225 }
226
UploadToBufferObject(const Context * rsc,const Allocation * alloc)227 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
228 #ifndef RS_COMPATIBILITY_LIB
229 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
230
231 rsAssert(!alloc->mHal.state.type->getDimY());
232 rsAssert(!alloc->mHal.state.type->getDimZ());
233
234 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
235
236 if (!drv->bufferID) {
237 RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID);
238 }
239 if (!drv->bufferID) {
240 ALOGE("Upload to buffer object failed");
241 drv->uploadDeferred = true;
242 return;
243 }
244 RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
245 RSD_CALL_GL(glBufferData, drv->glTarget,
246 alloc->mHal.state.type->getPackedSizeBytes(),
247 alloc->mHal.drvState.lod[0].mallocPtr, GL_DYNAMIC_DRAW);
248 RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
249 rsdGLCheckError(rsc, "UploadToBufferObject");
250 #endif
251 }
252
253
DeriveYUVLayout(int yuv,Allocation::Hal::DrvState * state)254 static size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
255 #ifndef RS_COMPATIBILITY_LIB
256 // For the flexible YCbCr format, layout is initialized during call to
257 // Allocation::ioReceive. Return early and avoid clobberring any
258 // pre-existing layout.
259 if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
260 return 0;
261 }
262 #endif
263
264 // YUV only supports basic 2d
265 // so we can stash the plane pointers in the mipmap levels.
266 size_t uvSize = 0;
267 state->lod[1].dimX = state->lod[0].dimX / 2;
268 state->lod[1].dimY = state->lod[0].dimY / 2;
269 state->lod[2].dimX = state->lod[0].dimX / 2;
270 state->lod[2].dimY = state->lod[0].dimY / 2;
271 state->yuv.shift = 1;
272 state->yuv.step = 1;
273 state->lodCount = 3;
274
275 #ifndef RS_SERVER
276 switch(yuv) {
277 case HAL_PIXEL_FORMAT_YV12:
278 state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
279 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
280 (state->lod[0].stride * state->lod[0].dimY);
281 uvSize += state->lod[2].stride * state->lod[2].dimY;
282
283 state->lod[1].stride = state->lod[2].stride;
284 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
285 (state->lod[2].stride * state->lod[2].dimY);
286 uvSize += state->lod[1].stride * state->lod[2].dimY;
287 break;
288 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
289 //state->lod[1].dimX = state->lod[0].dimX;
290 state->lod[1].stride = state->lod[0].stride;
291 state->lod[2].stride = state->lod[0].stride;
292 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
293 (state->lod[0].stride * state->lod[0].dimY);
294 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1;
295 uvSize += state->lod[1].stride * state->lod[1].dimY;
296 state->yuv.step = 2;
297 break;
298 default:
299 rsAssert(0);
300 }
301 #endif
302 return uvSize;
303 }
304
AllocationBuildPointerTable(const Context * rsc,const Allocation * alloc,const Type * type,uint8_t * ptr,size_t requiredAlignment)305 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
306 const Type *type, uint8_t *ptr, size_t requiredAlignment) {
307 alloc->mHal.drvState.lod[0].dimX = type->getDimX();
308 alloc->mHal.drvState.lod[0].dimY = type->getDimY();
309 alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
310 alloc->mHal.drvState.lod[0].mallocPtr = 0;
311 // Stride needs to be aligned to a boundary defined by requiredAlignment!
312 size_t stride = alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
313 alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment);
314 alloc->mHal.drvState.lodCount = type->getLODCount();
315 alloc->mHal.drvState.faceCount = type->getDimFaces();
316
317 size_t offsets[Allocation::MAX_LOD];
318 memset(offsets, 0, sizeof(offsets));
319
320 size_t o = alloc->mHal.drvState.lod[0].stride * rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
321 rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
322 if (alloc->mHal.state.yuv) {
323 o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
324
325 for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
326 offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
327 }
328 } else if(alloc->mHal.drvState.lodCount > 1) {
329 uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
330 uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
331 uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
332 for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
333 alloc->mHal.drvState.lod[lod].dimX = tx;
334 alloc->mHal.drvState.lod[lod].dimY = ty;
335 alloc->mHal.drvState.lod[lod].dimZ = tz;
336 alloc->mHal.drvState.lod[lod].stride =
337 rsRound(tx * type->getElementSizeBytes(), requiredAlignment);
338 offsets[lod] = o;
339 o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
340 if (tx > 1) tx >>= 1;
341 if (ty > 1) ty >>= 1;
342 if (tz > 1) tz >>= 1;
343 }
344 }
345
346 alloc->mHal.drvState.faceOffset = o;
347
348 alloc->mHal.drvState.lod[0].mallocPtr = ptr;
349 for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
350 alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
351 }
352
353 size_t allocSize = alloc->mHal.drvState.faceOffset;
354 if(alloc->mHal.drvState.faceCount) {
355 allocSize *= 6;
356 }
357
358 return allocSize;
359 }
360
AllocationBuildPointerTable(const Context * rsc,const Allocation * alloc,const Type * type,uint8_t * ptr)361 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
362 const Type *type, uint8_t *ptr) {
363 return AllocationBuildPointerTable(rsc, alloc, type, ptr, Allocation::kMinimumRSAlignment);
364 }
365
allocAlignedMemory(size_t allocSize,bool forceZero,size_t requiredAlignment)366 static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero, size_t requiredAlignment) {
367 // We align all allocations to a boundary defined by requiredAlignment.
368 uint8_t* ptr = (uint8_t *)memalign(requiredAlignment, allocSize);
369 if (!ptr) {
370 return nullptr;
371 }
372 if (forceZero) {
373 memset(ptr, 0, allocSize);
374 }
375 return ptr;
376 }
377
rsdAllocationInitStrided(const Context * rsc,Allocation * alloc,bool forceZero,size_t requiredAlignment)378 bool rsdAllocationInitStrided(const Context *rsc, Allocation *alloc, bool forceZero, size_t requiredAlignment) {
379 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
380 if (!drv) {
381 return false;
382 }
383 alloc->mHal.drv = drv;
384
385 // Check if requiredAlignment is power of 2, also requiredAlignment should be larger or equal than kMinimumRSAlignment.
386 if ((requiredAlignment & (requiredAlignment-1)) != 0 || requiredAlignment < Allocation::kMinimumRSAlignment) {
387 ALOGE("requiredAlignment must be power of 2");
388 return false;
389 }
390 // Calculate the object size.
391 size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), nullptr, requiredAlignment);
392
393 uint8_t * ptr = nullptr;
394 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
395
396 } else if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
397 // Allocation is allocated when the surface is created
398 // in getSurface
399 #ifdef RS_COMPATIBILITY_LIB
400 } else if (alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED)) {
401 if (alloc->mHal.state.userProvidedPtr == nullptr) {
402 ALOGE("User-backed buffer pointer cannot be null");
403 return false;
404 }
405 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
406 ALOGE("User-allocated buffers must not have multiple faces or LODs");
407 return false;
408 }
409
410 drv->useUserProvidedPtr = true;
411 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
412 #endif
413 } else if (alloc->mHal.state.userProvidedPtr != nullptr) {
414 // user-provided allocation
415 // limitations: no faces, no LOD, USAGE_SCRIPT or SCRIPT+TEXTURE only
416 if (!(alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED) ||
417 alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE))) {
418 ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT | USAGE_SHARED or USAGE_SCRIPT | USAGE_SHARED | USAGE_GRAPHICS_TEXTURE");
419 return false;
420 }
421 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
422 ALOGE("User-allocated buffers must not have multiple faces or LODs");
423 return false;
424 }
425
426 // rows must be aligned based on requiredAlignment.
427 // validate that here, otherwise fall back to not use the user-backed allocation
428 if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % requiredAlignment) != 0) {
429 ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation");
430 drv->useUserProvidedPtr = false;
431
432 ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment);
433 if (!ptr) {
434 alloc->mHal.drv = nullptr;
435 free(drv);
436 return false;
437 }
438
439 } else {
440 drv->useUserProvidedPtr = true;
441 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
442 }
443 } else {
444 ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment);
445 if (!ptr) {
446 alloc->mHal.drv = nullptr;
447 free(drv);
448 return false;
449 }
450 }
451 // Build the pointer tables
452 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr, requiredAlignment);
453 if(allocSize != verifySize) {
454 rsAssert(!"Size mismatch");
455 }
456
457 #ifndef RS_SERVER
458 drv->glTarget = GL_NONE;
459 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
460 if (alloc->mHal.state.hasFaces) {
461 drv->glTarget = GL_TEXTURE_CUBE_MAP;
462 } else {
463 drv->glTarget = GL_TEXTURE_2D;
464 }
465 } else {
466 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
467 drv->glTarget = GL_ARRAY_BUFFER;
468 }
469 }
470 #endif
471
472 #ifndef RS_COMPATIBILITY_LIB
473 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
474 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
475 #else
476 drv->glType = 0;
477 drv->glFormat = 0;
478 #endif
479
480 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
481 drv->uploadDeferred = true;
482 }
483
484
485 drv->readBackFBO = nullptr;
486
487 // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted
488 if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) {
489 rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0);
490 }
491
492
493 #ifdef RS_FIND_OFFSETS
494 ALOGE("pointer for allocation: %p", alloc);
495 ALOGE("pointer for allocation.drv: %p", &alloc->mHal.drv);
496 #endif
497
498
499 return true;
500 }
501
rsdAllocationInit(const Context * rsc,Allocation * alloc,bool forceZero)502 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
503 return rsdAllocationInitStrided(rsc, alloc, forceZero, Allocation::kMinimumRSAlignment);
504 }
505
rsdAllocationAdapterOffset(const Context * rsc,const Allocation * alloc)506 void rsdAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
507 //ALOGE("rsdAllocationAdapterOffset");
508
509 // Get a base pointer to the new LOD
510 const Allocation *base = alloc->mHal.state.baseAlloc;
511 const Type *type = alloc->mHal.state.type;
512 if (base == nullptr) {
513 return;
514 }
515
516 //ALOGE("rsdAllocationAdapterOffset %p %p", ptrA, ptrB);
517 //ALOGE("rsdAllocationAdapterOffset lodCount %i", alloc->mHal.drvState.lodCount);
518
519 const int lodBias = alloc->mHal.state.originLOD;
520 uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
521 for (uint32_t lod=0; lod < lodCount; lod++) {
522 alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
523 alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(alloc,
524 alloc->mHal.state.originX, alloc->mHal.state.originY, alloc->mHal.state.originZ,
525 lodBias, (RsAllocationCubemapFace)alloc->mHal.state.originFace);
526 }
527 }
528
rsdAllocationAdapterInit(const Context * rsc,Allocation * alloc)529 bool rsdAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
530 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
531 if (!drv) {
532 return false;
533 }
534 alloc->mHal.drv = drv;
535
536 // We need to build an allocation that looks like a subset of the parent allocation
537 rsdAllocationAdapterOffset(rsc, alloc);
538
539 return true;
540 }
541
rsdAllocationDestroy(const Context * rsc,Allocation * alloc)542 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
543 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
544
545 if (alloc->mHal.state.baseAlloc == nullptr) {
546 #ifndef RS_COMPATIBILITY_LIB
547 if (drv->bufferID) {
548 // Causes a SW crash....
549 //ALOGV(" mBufferID %i", mBufferID);
550 //glDeleteBuffers(1, &mBufferID);
551 //mBufferID = 0;
552 }
553 if (drv->textureID) {
554 RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
555 drv->textureID = 0;
556 }
557 if (drv->renderTargetID) {
558 RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
559 drv->renderTargetID = 0;
560 }
561 #endif
562
563 if (alloc->mHal.drvState.lod[0].mallocPtr) {
564 // don't free user-allocated ptrs or IO_OUTPUT buffers
565 if (!(drv->useUserProvidedPtr) &&
566 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
567 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
568 free(alloc->mHal.drvState.lod[0].mallocPtr);
569 }
570 alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
571 }
572
573 #ifndef RS_COMPATIBILITY_LIB
574 if (drv->readBackFBO != nullptr) {
575 delete drv->readBackFBO;
576 drv->readBackFBO = nullptr;
577 }
578
579 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
580 (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
581
582 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
583 ANativeWindow *nw = drv->wndSurface;
584 if (nw) {
585 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
586 mapper.unlock(drv->wndBuffer->handle);
587 int32_t r = nw->cancelBuffer(nw, drv->wndBuffer, -1);
588
589 drv->wndSurface = nullptr;
590 native_window_api_disconnect(nw, NATIVE_WINDOW_API_CPU);
591 nw->decStrong(nullptr);
592 }
593 }
594 #endif
595 }
596
597 free(drv);
598 alloc->mHal.drv = nullptr;
599 }
600
rsdAllocationResize(const Context * rsc,const Allocation * alloc,const Type * newType,bool zeroNew)601 void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
602 const Type *newType, bool zeroNew) {
603 const uint32_t oldDimX = alloc->mHal.drvState.lod[0].dimX;
604 const uint32_t dimX = newType->getDimX();
605
606 // can't resize Allocations with user-allocated buffers
607 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
608 ALOGE("Resize cannot be called on a USAGE_SHARED allocation");
609 return;
610 }
611 void * oldPtr = alloc->mHal.drvState.lod[0].mallocPtr;
612 // Calculate the object size
613 size_t s = AllocationBuildPointerTable(rsc, alloc, newType, nullptr);
614 uint8_t *ptr = (uint8_t *)realloc(oldPtr, s);
615 // Build the relative pointer tables.
616 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr);
617 if(s != verifySize) {
618 rsAssert(!"Size mismatch");
619 }
620
621
622 if (dimX > oldDimX) {
623 size_t stride = alloc->mHal.state.elementSizeBytes;
624 memset(((uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr) + stride * oldDimX,
625 0, stride * (dimX - oldDimX));
626 }
627 }
628
rsdAllocationSyncFromFBO(const Context * rsc,const Allocation * alloc)629 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
630 #ifndef RS_COMPATIBILITY_LIB
631 if (!alloc->getIsScript()) {
632 return; // nothing to sync
633 }
634
635 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
636 RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer;
637
638 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
639 if (!drv->textureID && !drv->renderTargetID) {
640 return; // nothing was rendered here yet, so nothing to sync
641 }
642 if (drv->readBackFBO == nullptr) {
643 drv->readBackFBO = new RsdFrameBufferObj();
644 drv->readBackFBO->setColorTarget(drv, 0);
645 drv->readBackFBO->setDimensions(alloc->getType()->getDimX(),
646 alloc->getType()->getDimY());
647 }
648
649 // Bind the framebuffer object so we can read back from it
650 drv->readBackFBO->setActive(rsc);
651
652 // Do the readback
653 RSD_CALL_GL(glReadPixels, 0, 0, alloc->mHal.drvState.lod[0].dimX,
654 alloc->mHal.drvState.lod[0].dimY,
655 drv->glFormat, drv->glType, alloc->mHal.drvState.lod[0].mallocPtr);
656
657 // Revert framebuffer to its original
658 lastFbo->setActive(rsc);
659 #endif
660 }
661
662
rsdAllocationSyncAll(const Context * rsc,const Allocation * alloc,RsAllocationUsageType src)663 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
664 RsAllocationUsageType src) {
665 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
666
667 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
668 if(!alloc->getIsRenderTarget()) {
669 rsc->setError(RS_ERROR_FATAL_DRIVER,
670 "Attempting to sync allocation from render target, "
671 "for non-render target allocation");
672 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
673 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
674 "render target");
675 } else {
676 rsdAllocationSyncFromFBO(rsc, alloc);
677 }
678 return;
679 }
680
681 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT || src == RS_ALLOCATION_USAGE_SHARED);
682
683 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
684 UploadToTexture(rsc, alloc);
685 } else {
686 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) &&
687 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
688 AllocateRenderTarget(rsc, alloc);
689 }
690 }
691 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
692 UploadToBufferObject(rsc, alloc);
693 }
694
695 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
696
697 if (src == RS_ALLOCATION_USAGE_SHARED) {
698 // just a memory fence for the CPU driver
699 // vendor drivers probably want to flush any dirty cachelines for
700 // this particular Allocation
701 __sync_synchronize();
702 }
703 }
704
705 drv->uploadDeferred = false;
706 }
707
rsdAllocationMarkDirty(const Context * rsc,const Allocation * alloc)708 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
709 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
710 drv->uploadDeferred = true;
711 }
712
713 #ifndef RS_COMPATIBILITY_LIB
IoGetBuffer(const Context * rsc,Allocation * alloc,ANativeWindow * nw)714 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
715 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
716
717 int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer);
718 if (r) {
719 rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer.");
720 return false;
721 }
722
723 // Must lock the whole surface
724 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
725 Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height);
726
727 void *dst = nullptr;
728 mapper.lock(drv->wndBuffer->handle,
729 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
730 bounds, &dst);
731 alloc->mHal.drvState.lod[0].mallocPtr = dst;
732 alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
733 rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0);
734
735 return true;
736 }
737 #endif
738
rsdAllocationSetSurface(const Context * rsc,Allocation * alloc,ANativeWindow * nw)739 void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
740 #ifndef RS_COMPATIBILITY_LIB
741 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
742 ANativeWindow *old = drv->wndSurface;
743
744 if (nw) {
745 nw->incStrong(nullptr);
746 }
747
748 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
749 //TODO finish support for render target + script
750 drv->wnd = nw;
751 return;
752 }
753
754 // Cleanup old surface if there is one.
755 if (drv->wndSurface) {
756 ANativeWindow *old = drv->wndSurface;
757 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
758 mapper.unlock(drv->wndBuffer->handle);
759 old->cancelBuffer(old, drv->wndBuffer, -1);
760 drv->wndSurface = nullptr;
761
762 native_window_api_disconnect(old, NATIVE_WINDOW_API_CPU);
763 old->decStrong(nullptr);
764 }
765
766 if (nw != nullptr) {
767 int32_t r;
768 uint32_t flags = 0;
769
770 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
771 flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
772 }
773 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
774 flags |= GRALLOC_USAGE_HW_RENDER;
775 }
776
777 r = native_window_api_connect(nw, NATIVE_WINDOW_API_CPU);
778 if (r) {
779 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
780 goto error;
781 }
782
783 r = native_window_set_usage(nw, flags);
784 if (r) {
785 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
786 goto error;
787 }
788
789 r = native_window_set_buffers_dimensions(nw, alloc->mHal.drvState.lod[0].dimX,
790 alloc->mHal.drvState.lod[0].dimY);
791 if (r) {
792 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions.");
793 goto error;
794 }
795
796 int format = 0;
797 const Element *e = alloc->mHal.state.type->getElement();
798 if ((e->getType() != RS_TYPE_UNSIGNED_8) ||
799 (e->getVectorSize() != 4)) {
800 // We do not check for RGBA, RGBx, to allow for interop with U8_4
801
802 rsc->setError(RS_ERROR_DRIVER, "Surface passed to setSurface is not U8_4, RGBA.");
803 goto error;
804 }
805 format = PIXEL_FORMAT_RGBA_8888;
806
807 r = native_window_set_buffers_format(nw, format);
808 if (r) {
809 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer format.");
810 goto error;
811 }
812
813 IoGetBuffer(rsc, alloc, nw);
814 drv->wndSurface = nw;
815 }
816
817 return;
818
819 error:
820
821 if (nw) {
822 nw->decStrong(nullptr);
823 }
824
825
826 #endif
827 }
828
rsdAllocationIoSend(const Context * rsc,Allocation * alloc)829 void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
830 #ifndef RS_COMPATIBILITY_LIB
831 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
832 ANativeWindow *nw = drv->wndSurface;
833 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
834 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
835 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
836 return;
837 }
838 if (nw) {
839 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
840 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
841 mapper.unlock(drv->wndBuffer->handle);
842 int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
843 if (r) {
844 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
845 return;
846 }
847
848 IoGetBuffer(rsc, alloc, nw);
849 }
850 } else {
851 rsc->setError(RS_ERROR_DRIVER, "Sent IO buffer with no attached surface.");
852 return;
853 }
854 #endif
855 }
856
rsdAllocationIoReceive(const Context * rsc,Allocation * alloc)857 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
858 #ifndef RS_COMPATIBILITY_LIB
859 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
860 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
861 drv->surfaceTexture->updateTexImage();
862 }
863 #endif
864 if (alloc->mHal.state.yuv) {
865 DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
866 }
867 }
868
869
rsdAllocationData1D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t lod,size_t count,const void * data,size_t sizeBytes)870 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
871 uint32_t xoff, uint32_t lod, size_t count,
872 const void *data, size_t sizeBytes) {
873 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
874
875 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
876 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
877 size_t size = count * eSize;
878 if (ptr != data) {
879 // Skip the copy if we are the same allocation. This can arise from
880 // our Bitmap optimization, where we share the same storage.
881 if (alloc->mHal.state.hasReferences) {
882 alloc->incRefs(data, count);
883 alloc->decRefs(ptr, count);
884 }
885 memcpy(ptr, data, size);
886 }
887 drv->uploadDeferred = true;
888 }
889
rsdAllocationData2D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t lod,RsAllocationCubemapFace face,uint32_t w,uint32_t h,const void * data,size_t sizeBytes,size_t stride)890 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
891 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
892 uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
893 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
894
895 size_t eSize = alloc->mHal.state.elementSizeBytes;
896 size_t lineSize = eSize * w;
897 if (!stride) {
898 stride = lineSize;
899 }
900
901 if (alloc->mHal.drvState.lod[0].mallocPtr) {
902 const uint8_t *src = static_cast<const uint8_t *>(data);
903 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
904 if (dst == src) {
905 // Skip the copy if we are the same allocation. This can arise from
906 // our Bitmap optimization, where we share the same storage.
907 drv->uploadDeferred = true;
908 return;
909 }
910
911 for (uint32_t line=yoff; line < (yoff+h); line++) {
912 if (alloc->mHal.state.hasReferences) {
913 alloc->incRefs(src, w);
914 alloc->decRefs(dst, w);
915 }
916 memcpy(dst, src, lineSize);
917 src += stride;
918 dst += alloc->mHal.drvState.lod[lod].stride;
919 }
920 if (alloc->mHal.state.yuv) {
921 size_t clineSize = lineSize;
922 int lod = 1;
923 int maxLod = 2;
924 if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) {
925 maxLod = 3;
926 clineSize >>= 1;
927 } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
928 lod = 2;
929 maxLod = 3;
930 }
931
932 while (lod < maxLod) {
933 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
934
935 for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) {
936 memcpy(dst, src, clineSize);
937 // When copying from an array to an Allocation, the src pointer
938 // to the array should just move by the number of bytes copied.
939 src += clineSize;
940 dst += alloc->mHal.drvState.lod[lod].stride;
941 }
942 lod++;
943 }
944
945 }
946 drv->uploadDeferred = true;
947 } else {
948 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
949 }
950 }
951
rsdAllocationData3D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t lod,uint32_t w,uint32_t h,uint32_t d,const void * data,size_t sizeBytes,size_t stride)952 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
953 uint32_t xoff, uint32_t yoff, uint32_t zoff,
954 uint32_t lod,
955 uint32_t w, uint32_t h, uint32_t d, const void *data,
956 size_t sizeBytes, size_t stride) {
957 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
958
959 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
960 uint32_t lineSize = eSize * w;
961 if (!stride) {
962 stride = lineSize;
963 }
964
965 if (alloc->mHal.drvState.lod[0].mallocPtr) {
966 const uint8_t *src = static_cast<const uint8_t *>(data);
967 for (uint32_t z = zoff; z < (d + zoff); z++) {
968 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
969 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
970 if (dst == src) {
971 // Skip the copy if we are the same allocation. This can arise from
972 // our Bitmap optimization, where we share the same storage.
973 drv->uploadDeferred = true;
974 return;
975 }
976
977 for (uint32_t line=yoff; line < (yoff+h); line++) {
978 if (alloc->mHal.state.hasReferences) {
979 alloc->incRefs(src, w);
980 alloc->decRefs(dst, w);
981 }
982 memcpy(dst, src, lineSize);
983 src += stride;
984 dst += alloc->mHal.drvState.lod[lod].stride;
985 }
986 }
987 drv->uploadDeferred = true;
988 }
989 }
990
rsdAllocationRead1D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t lod,size_t count,void * data,size_t sizeBytes)991 void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
992 uint32_t xoff, uint32_t lod, size_t count,
993 void *data, size_t sizeBytes) {
994 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
995 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
996 if (data != ptr) {
997 // Skip the copy if we are the same allocation. This can arise from
998 // our Bitmap optimization, where we share the same storage.
999 memcpy(data, ptr, count * eSize);
1000 }
1001 }
1002
rsdAllocationRead2D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t lod,RsAllocationCubemapFace face,uint32_t w,uint32_t h,void * data,size_t sizeBytes,size_t stride)1003 void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
1004 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
1005 uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) {
1006 size_t eSize = alloc->mHal.state.elementSizeBytes;
1007 size_t lineSize = eSize * w;
1008 if (!stride) {
1009 stride = lineSize;
1010 }
1011
1012 if (alloc->mHal.drvState.lod[0].mallocPtr) {
1013 uint8_t *dst = static_cast<uint8_t *>(data);
1014 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
1015 if (dst == src) {
1016 // Skip the copy if we are the same allocation. This can arise from
1017 // our Bitmap optimization, where we share the same storage.
1018 return;
1019 }
1020
1021 for (uint32_t line=yoff; line < (yoff+h); line++) {
1022 memcpy(dst, src, lineSize);
1023 dst += stride;
1024 src += alloc->mHal.drvState.lod[lod].stride;
1025 }
1026 } else {
1027 ALOGE("Add code to readback from non-script memory");
1028 }
1029 }
1030
1031
rsdAllocationRead3D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t lod,uint32_t w,uint32_t h,uint32_t d,void * data,size_t sizeBytes,size_t stride)1032 void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
1033 uint32_t xoff, uint32_t yoff, uint32_t zoff,
1034 uint32_t lod,
1035 uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) {
1036 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
1037 uint32_t lineSize = eSize * w;
1038 if (!stride) {
1039 stride = lineSize;
1040 }
1041
1042 if (alloc->mHal.drvState.lod[0].mallocPtr) {
1043 uint8_t *dst = static_cast<uint8_t *>(data);
1044 for (uint32_t z = zoff; z < (d + zoff); z++) {
1045 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
1046 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1047 if (dst == src) {
1048 // Skip the copy if we are the same allocation. This can arise from
1049 // our Bitmap optimization, where we share the same storage.
1050 return;
1051 }
1052
1053 for (uint32_t line=yoff; line < (yoff+h); line++) {
1054 memcpy(dst, src, lineSize);
1055 dst += stride;
1056 src += alloc->mHal.drvState.lod[lod].stride;
1057 }
1058 }
1059 }
1060 }
1061
rsdAllocationLock1D(const android::renderscript::Context * rsc,const android::renderscript::Allocation * alloc)1062 void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
1063 const android::renderscript::Allocation *alloc) {
1064 return alloc->mHal.drvState.lod[0].mallocPtr;
1065 }
1066
rsdAllocationUnlock1D(const android::renderscript::Context * rsc,const android::renderscript::Allocation * alloc)1067 void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
1068 const android::renderscript::Allocation *alloc) {
1069
1070 }
1071
rsdAllocationData1D_alloc(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstLod,size_t count,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcLod)1072 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
1073 const android::renderscript::Allocation *dstAlloc,
1074 uint32_t dstXoff, uint32_t dstLod, size_t count,
1075 const android::renderscript::Allocation *srcAlloc,
1076 uint32_t srcXoff, uint32_t srcLod) {
1077 }
1078
1079
rsdAllocationData2D_alloc_script(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstLod,RsAllocationCubemapFace dstFace,uint32_t w,uint32_t h,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcLod,RsAllocationCubemapFace srcFace)1080 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
1081 const android::renderscript::Allocation *dstAlloc,
1082 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
1083 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
1084 const android::renderscript::Allocation *srcAlloc,
1085 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
1086 RsAllocationCubemapFace srcFace) {
1087 size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
1088 for (uint32_t i = 0; i < h; i ++) {
1089 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
1090 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
1091 memcpy(dstPtr, srcPtr, w * elementSize);
1092
1093 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
1094 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
1095 }
1096 }
1097
rsdAllocationData3D_alloc_script(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstZoff,uint32_t dstLod,uint32_t w,uint32_t h,uint32_t d,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcZoff,uint32_t srcLod)1098 void rsdAllocationData3D_alloc_script(const android::renderscript::Context *rsc,
1099 const android::renderscript::Allocation *dstAlloc,
1100 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod,
1101 uint32_t w, uint32_t h, uint32_t d,
1102 const android::renderscript::Allocation *srcAlloc,
1103 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod) {
1104 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
1105 for (uint32_t j = 0; j < d; j++) {
1106 for (uint32_t i = 0; i < h; i ++) {
1107 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j,
1108 dstLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1109 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j,
1110 srcLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1111 memcpy(dstPtr, srcPtr, w * elementSize);
1112
1113 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
1114 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
1115 }
1116 }
1117 }
1118
rsdAllocationData2D_alloc(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstLod,RsAllocationCubemapFace dstFace,uint32_t w,uint32_t h,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcLod,RsAllocationCubemapFace srcFace)1119 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
1120 const android::renderscript::Allocation *dstAlloc,
1121 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
1122 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
1123 const android::renderscript::Allocation *srcAlloc,
1124 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
1125 RsAllocationCubemapFace srcFace) {
1126 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
1127 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
1128 "yet implemented.");
1129 return;
1130 }
1131 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
1132 dstLod, dstFace, w, h, srcAlloc,
1133 srcXoff, srcYoff, srcLod, srcFace);
1134 }
1135
rsdAllocationData3D_alloc(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstZoff,uint32_t dstLod,uint32_t w,uint32_t h,uint32_t d,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcZoff,uint32_t srcLod)1136 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
1137 const android::renderscript::Allocation *dstAlloc,
1138 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
1139 uint32_t dstLod,
1140 uint32_t w, uint32_t h, uint32_t d,
1141 const android::renderscript::Allocation *srcAlloc,
1142 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
1143 uint32_t srcLod) {
1144 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
1145 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
1146 "yet implemented.");
1147 return;
1148 }
1149 rsdAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
1150 dstLod, w, h, d, srcAlloc,
1151 srcXoff, srcYoff, srcZoff, srcLod);
1152 }
1153
rsdAllocationElementData(const Context * rsc,const Allocation * alloc,uint32_t x,uint32_t y,uint32_t z,const void * data,uint32_t cIdx,size_t sizeBytes)1154 void rsdAllocationElementData(const Context *rsc, const Allocation *alloc,
1155 uint32_t x, uint32_t y, uint32_t z,
1156 const void *data, uint32_t cIdx, size_t sizeBytes) {
1157 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
1158
1159 uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1160
1161 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
1162 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
1163
1164 if (alloc->mHal.state.hasReferences) {
1165 e->incRefs(data);
1166 e->decRefs(ptr);
1167 }
1168
1169 memcpy(ptr, data, sizeBytes);
1170 drv->uploadDeferred = true;
1171 }
1172
rsdAllocationElementRead(const Context * rsc,const Allocation * alloc,uint32_t x,uint32_t y,uint32_t z,void * data,uint32_t cIdx,size_t sizeBytes)1173 void rsdAllocationElementRead(const Context *rsc, const Allocation *alloc,
1174 uint32_t x, uint32_t y, uint32_t z,
1175 void *data, uint32_t cIdx, size_t sizeBytes) {
1176 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
1177
1178 uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1179
1180 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
1181 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
1182
1183 memcpy(data, ptr, sizeBytes);
1184 }
1185
mip565(const Allocation * alloc,int lod,RsAllocationCubemapFace face)1186 static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1187 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1188 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1189
1190 for (uint32_t y=0; y < h; y++) {
1191 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1192 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2, lod, face);
1193 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2+1, lod, face);
1194
1195 for (uint32_t x=0; x < w; x++) {
1196 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
1197 oPtr ++;
1198 i1 += 2;
1199 i2 += 2;
1200 }
1201 }
1202 }
1203
mip8888(const Allocation * alloc,int lod,RsAllocationCubemapFace face)1204 static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1205 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1206 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1207
1208 for (uint32_t y=0; y < h; y++) {
1209 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1210 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
1211 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
1212
1213 for (uint32_t x=0; x < w; x++) {
1214 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
1215 oPtr ++;
1216 i1 += 2;
1217 i2 += 2;
1218 }
1219 }
1220 }
1221
mip8(const Allocation * alloc,int lod,RsAllocationCubemapFace face)1222 static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1223 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1224 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1225
1226 for (uint32_t y=0; y < h; y++) {
1227 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1228 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
1229 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
1230
1231 for (uint32_t x=0; x < w; x++) {
1232 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
1233 oPtr ++;
1234 i1 += 2;
1235 i2 += 2;
1236 }
1237 }
1238 }
1239
rsdAllocationGenerateMipmaps(const Context * rsc,const Allocation * alloc)1240 void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) {
1241 if(!alloc->mHal.drvState.lod[0].mallocPtr) {
1242 return;
1243 }
1244 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
1245 for (uint32_t face = 0; face < numFaces; face ++) {
1246 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) {
1247 switch (alloc->getType()->getElement()->getSizeBits()) {
1248 case 32:
1249 mip8888(alloc, lod, (RsAllocationCubemapFace)face);
1250 break;
1251 case 16:
1252 mip565(alloc, lod, (RsAllocationCubemapFace)face);
1253 break;
1254 case 8:
1255 mip8(alloc, lod, (RsAllocationCubemapFace)face);
1256 break;
1257 }
1258 }
1259 }
1260 }
1261
rsdAllocationGrallocBits(const android::renderscript::Context * rsc,android::renderscript::Allocation * alloc)1262 uint32_t rsdAllocationGrallocBits(const android::renderscript::Context *rsc,
1263 android::renderscript::Allocation *alloc)
1264 {
1265 return 0;
1266 }
1267
rsdAllocationUpdateCachedObject(const Context * rsc,const Allocation * alloc,rs_allocation * obj)1268 void rsdAllocationUpdateCachedObject(const Context *rsc,
1269 const Allocation *alloc,
1270 rs_allocation *obj)
1271 {
1272 obj->p = alloc;
1273 #ifdef __LP64__
1274 if (alloc != nullptr) {
1275 obj->r = alloc->mHal.drvState.lod[0].mallocPtr;
1276 obj->v1 = alloc->mHal.drv;
1277 obj->v2 = (void *)alloc->mHal.drvState.lod[0].stride;
1278 } else {
1279 obj->r = nullptr;
1280 obj->v1 = nullptr;
1281 obj->v2 = nullptr;
1282 }
1283 #endif
1284 }
1285