1// Copyright (C) 2012 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma version(1)
16
17#pragma rs java_package_name(com.android.scenegraph)
18
19#include "scenegraph_objects.rsh"
20
21//#define DEBUG_PARAMS
22static inline void debugParam(SgShaderParam *p, SgShaderParamData *pData) {
23    rsDebug("____________ Param ____________", p);
24    printName(pData->paramName);
25    rsDebug("bufferOffset", p->bufferOffset);
26    rsDebug("type ", pData->type);
27    rsDebug("data timestamp ", pData->timestamp);
28    rsDebug("param timestamp", p->dataTimestamp);
29
30    const SgTransform *pTransform = NULL;
31    if (rsIsObject(pData->transform)) {
32        pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
33
34        rsDebug("transform", pTransform);
35        printName(pTransform->name);
36        rsDebug("timestamp", pTransform->timestamp);
37        rsDebug("param timestamp", p->transformTimestamp);
38    }
39
40    const SgLight *pLight = NULL;
41    if (rsIsObject(pData->light)) {
42        pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
43        printLightInfo(pLight);
44    }
45}
46
47static inline void writeFloatData(float *ptr, const float4 *input, uint32_t vecSize) {
48#ifdef DEBUG_PARAMS
49    rsDebug("Writing value ", *input);
50    rsDebug("Writing vec size ", vecSize);
51#endif // DEBUG_PARAMS
52
53    switch (vecSize) {
54    case 1:
55        *ptr = input->x;
56        break;
57    case 2:
58        *((float2*)ptr) = (*input).xy;
59        break;
60    case 3:
61        *((float3*)ptr) = (*input).xyz;
62        break;
63    case 4:
64        *((float4*)ptr) = *input;
65        break;
66    }
67}
68
69static inline bool processParam(SgShaderParam *p, SgShaderParamData *pData,
70                         uint8_t *constantBuffer,
71                         const SgCamera *currentCam,
72                         SgFragmentShader *shader) {
73    bool isDataOnly = (pData->type > SHADER_PARAM_DATA_ONLY);
74    const SgTransform *pTransform = NULL;
75    if (rsIsObject(pData->transform)) {
76        pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
77    }
78
79    if (isDataOnly) {
80        // If we are a transform param and our transform is unchanged, nothing to do
81        if (pTransform) {
82            if (p->transformTimestamp == pTransform->timestamp) {
83                return false;
84            }
85            p->transformTimestamp = pTransform->timestamp;
86        } else {
87            if (p->dataTimestamp == pData->timestamp) {
88                return false;
89            }
90            p->dataTimestamp = pData->timestamp;
91        }
92    }
93
94    const SgLight *pLight = NULL;
95    if (rsIsObject(pData->light)) {
96        pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
97    }
98
99    uint8_t *dataPtr = NULL;
100    const SgTexture *tex = NULL;
101    if (pData->type == SHADER_PARAM_TEXTURE) {
102        tex = rsGetElementAt(pData->texture, 0);
103    } else {
104        dataPtr = constantBuffer + p->bufferOffset;
105    }
106
107    switch (pData->type) {
108    case SHADER_PARAM_TEXTURE:
109        rsgBindTexture(shader->program, p->bufferOffset, tex->texture);
110        break;
111    case SHADER_PARAM_FLOAT4_DATA:
112        writeFloatData((float*)dataPtr, &pData->float_value, p->float_vecSize);
113        break;
114    case SHADER_PARAM_FLOAT4_CAMERA_POS:
115        writeFloatData((float*)dataPtr, &currentCam->position, p->float_vecSize);
116        break;
117    case SHADER_PARAM_FLOAT4_CAMERA_DIR: break;
118    case SHADER_PARAM_FLOAT4_LIGHT_COLOR:
119        writeFloatData((float*)dataPtr, &pLight->color, p->float_vecSize);
120        break;
121    case SHADER_PARAM_FLOAT4_LIGHT_POS:
122        writeFloatData((float*)dataPtr, &pLight->position, p->float_vecSize);
123        break;
124    case SHADER_PARAM_FLOAT4_LIGHT_DIR: break;
125
126    case SHADER_PARAM_TRANSFORM_DATA:
127        rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat);
128        break;
129    case SHADER_PARAM_TRANSFORM_VIEW:
130        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->view);
131        break;
132    case SHADER_PARAM_TRANSFORM_PROJ:
133        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->proj);
134        break;
135    case SHADER_PARAM_TRANSFORM_VIEW_PROJ:
136        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->viewProj);
137        break;
138    case SHADER_PARAM_TRANSFORM_MODEL:
139        rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat);
140        break;
141    case SHADER_PARAM_TRANSFORM_MODEL_VIEW:
142        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->view);
143        rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr,
144                             (rs_matrix4x4*)dataPtr,
145                             &pTransform->globalMat);
146        break;
147    case SHADER_PARAM_TRANSFORM_MODEL_VIEW_PROJ:
148        rsMatrixLoad((rs_matrix4x4*)dataPtr, &currentCam->viewProj);
149        rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr,
150                             (rs_matrix4x4*)dataPtr,
151                             &pTransform->globalMat);
152        break;
153    }
154    return true;
155}
156
157static inline void processAllParams(rs_allocation shaderConst,
158                             rs_allocation allParams,
159                             const SgCamera *camera) {
160    if (rsIsObject(shaderConst)) {
161        uint8_t *constantBuffer = (uint8_t*)rsGetElementAt(shaderConst, 0);
162
163        int numParams = 0;
164        if (rsIsObject(allParams)) {
165            numParams = rsAllocationGetDimX(allParams);
166        }
167        bool updated = false;
168        for (int i = 0; i < numParams; i ++) {
169            SgShaderParam *current = (SgShaderParam*)rsGetElementAt(allParams, i);
170            SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
171#ifdef DEBUG_PARAMS
172            debugParam(current, currentData);
173#endif // DEBUG_PARAMS
174            updated = processParam(current, currentData, constantBuffer, camera, NULL) || updated;
175        }
176    }
177}
178
179static inline void processTextureParams(SgFragmentShader *shader) {
180    int numParams = 0;
181    if (rsIsObject(shader->shaderTextureParams)) {
182        numParams = rsAllocationGetDimX(shader->shaderTextureParams);
183    }
184    for (int i = 0; i < numParams; i ++) {
185        SgShaderParam *current = (SgShaderParam*)rsGetElementAt(shader->shaderTextureParams, i);
186        SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
187#ifdef DEBUG_PARAMS
188        debugParam(current, currentData);
189#endif // DEBUG_PARAMS
190        processParam(current, currentData, NULL, NULL, shader);
191    }
192}
193