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