1 /*
2 * Copyright (C) 2012 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 <malloc.h>
18 #include <string.h>
19
20 #include "RenderScript.h"
21 #include "rsCppInternal.h"
22
23 // From system/graphics.h
24 enum {
25 HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar
26 HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x11, // NV21
27 };
28
29 using android::RSC::Element;
30 using android::RSC::RS;
31 using android::RSC::Type;
32 using android::RSC::sp;
33
calcElementCount()34 void Type::calcElementCount() {
35 bool hasLod = hasMipmaps();
36 uint32_t x = getX();
37 uint32_t y = getY();
38 uint32_t z = getZ();
39 uint32_t faces = 1;
40 if (hasFaces()) {
41 faces = 6;
42 }
43 if (x == 0) {
44 x = 1;
45 }
46 if (y == 0) {
47 y = 1;
48 }
49 if (z == 0) {
50 z = 1;
51 }
52
53 uint32_t count = x * y * z * faces;
54 while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
55 if(x > 1) {
56 x >>= 1;
57 }
58 if(y > 1) {
59 y >>= 1;
60 }
61 if(z > 1) {
62 z >>= 1;
63 }
64
65 count += x * y * z * faces;
66 }
67 mElementCount = count;
68 }
69
70
Type(void * id,sp<RS> rs)71 Type::Type(void *id, sp<RS> rs) : BaseObj(id, rs) {
72 mDimX = 0;
73 mDimY = 0;
74 mDimZ = 0;
75 mDimMipmaps = false;
76 mDimFaces = false;
77 mElement = nullptr;
78 mYuvFormat = RS_YUV_NONE;
79 }
80
updateFromNative()81 void Type::updateFromNative() {
82 BaseObj::updateFromNative();
83
84 /*
85 * We have 6 integers / pointers (uintptr_t) to obtain from the return buffer:
86 * mDimX (buffer[0]);
87 * mDimY (buffer[1]);
88 * mDimZ (buffer[2]);
89 * mDimLOD (buffer[3]);
90 * mDimFaces (buffer[4]);
91 * mElement (buffer[5]);
92 */
93 uintptr_t dataBuffer[6];
94 RS::dispatch->TypeGetNativeData(mRS->getContext(), getID(), dataBuffer, 6);
95
96 mDimX = (uint32_t)dataBuffer[0];
97 mDimY = (uint32_t)dataBuffer[1];
98 mDimZ = (uint32_t)dataBuffer[2];
99 mDimMipmaps = dataBuffer[3] == 1 ? true : false;
100 mDimFaces = dataBuffer[4] == 1 ? true : false;
101
102 uintptr_t elementID = dataBuffer[5];
103 if(elementID != 0) {
104 // Just create a new Element and update it from native.
105 sp<Element> e = new Element((void *)elementID, mRS);
106 e->updateFromNative();
107 mElement = e;
108 }
109 calcElementCount();
110 }
111
create(const sp<RS> & rs,const sp<const Element> & e,uint32_t dimX,uint32_t dimY,uint32_t dimZ)112 sp<const Type> Type::create(const sp<RS>& rs, const sp<const Element>& e, uint32_t dimX, uint32_t dimY, uint32_t dimZ) {
113 void * id = RS::dispatch->TypeCreate(rs->getContext(), e->getID(), dimX, dimY, dimZ, false, false, 0);
114 Type *t = new Type(id, rs);
115
116 t->mElement = e;
117 t->mDimX = dimX;
118 t->mDimY = dimY;
119 t->mDimZ = dimZ;
120 t->mDimMipmaps = false;
121 t->mDimFaces = false;
122 t->mYuvFormat = RS_YUV_NONE;
123
124 t->calcElementCount();
125
126 return t;
127 }
128
Builder(sp<RS> rs,sp<const Element> e)129 Type::Builder::Builder(sp<RS> rs, sp<const Element> e) {
130 mRS = rs.get();
131 mElement = e;
132 mDimX = 0;
133 mDimY = 0;
134 mDimZ = 0;
135 mDimMipmaps = false;
136 mDimFaces = false;
137 mYuvFormat = RS_YUV_NONE;
138 }
139
setX(uint32_t value)140 void Type::Builder::setX(uint32_t value) {
141 if(value < 1) {
142 ALOGE("Values of less than 1 for Dimension X are not valid.");
143 }
144 mDimX = value;
145 }
146
setY(uint32_t value)147 void Type::Builder::setY(uint32_t value) {
148 if(value < 1) {
149 ALOGE("Values of less than 1 for Dimension Y are not valid.");
150 }
151 mDimY = value;
152 }
153
setZ(uint32_t value)154 void Type::Builder::setZ(uint32_t value) {
155 if(value < 1) {
156 ALOGE("Values of less than 1 for Dimension Z are not valid.");
157 }
158 mDimZ = value;
159 }
160
setYuvFormat(RsYuvFormat format)161 void Type::Builder::setYuvFormat(RsYuvFormat format) {
162 if (format != RS_YUV_NONE && !(mElement->isCompatible(Element::YUV(mRS)))) {
163 ALOGE("Invalid element for use with YUV.");
164 return;
165 }
166
167 if (format != RS_YUV_NONE &&
168 format != RS_YUV_YV12 &&
169 format != RS_YUV_NV21 &&
170 format != RS_YUV_420_888) {
171 ALOGE("Invalid YUV format.");
172 return;
173 }
174 mYuvFormat = format;
175 }
176
177
setMipmaps(bool value)178 void Type::Builder::setMipmaps(bool value) {
179 mDimMipmaps = value;
180 }
181
setFaces(bool value)182 void Type::Builder::setFaces(bool value) {
183 mDimFaces = value;
184 }
185
create()186 sp<const Type> Type::Builder::create() {
187 if (mDimZ > 0) {
188 if ((mDimX < 1) || (mDimY < 1)) {
189 ALOGE("Both X and Y dimension required when Z is present.");
190 return nullptr;
191 }
192 if (mDimFaces) {
193 ALOGE("Cube maps not supported with 3D types.");
194 return nullptr;
195 }
196 }
197 if (mDimY > 0) {
198 if (mDimX < 1) {
199 ALOGE("X dimension required when Y is present.");
200 return nullptr;
201 }
202 }
203 if (mDimFaces) {
204 if (mDimY < 1) {
205 ALOGE("Cube maps require 2D Types.");
206 return nullptr;
207 }
208 }
209
210 if (mYuvFormat != RS_YUV_NONE) {
211 if (mDimZ || mDimFaces || mDimMipmaps) {
212 ALOGE("YUV only supports basic 2D.");
213 return nullptr;
214 }
215 }
216
217 if (mYuvFormat == RS_YUV_420_888) {
218 ALOGE("YUV_420_888 not supported.");
219 return nullptr;
220 }
221
222 void * id = RS::dispatch->TypeCreate(mRS->getContext(), mElement->getID(), mDimX, mDimY, mDimZ,
223 mDimMipmaps, mDimFaces, mYuvFormat);
224 Type *t = new Type(id, mRS);
225 t->mElement = mElement;
226 t->mDimX = mDimX;
227 t->mDimY = mDimY;
228 t->mDimZ = mDimZ;
229 t->mDimMipmaps = mDimMipmaps;
230 t->mDimFaces = mDimFaces;
231 t->mYuvFormat = mYuvFormat;
232
233 t->calcElementCount();
234 return t;
235 }
236
237