1// Copyright (C) 2011-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 "rs_graphics.rsh"
20#include "scenegraph_objects.rsh"
21
22rs_script gTransformScript;
23rs_script gCameraScript;
24rs_script gLightScript;
25rs_script gObjectParamsScript;
26rs_script gFragmentParamsScript;
27rs_script gVertexParamsScript;
28rs_script gCullScript;
29
30SgTransform *gRootNode;
31rs_allocation gCameras;
32rs_allocation gLights;
33rs_allocation gFragmentShaders;
34rs_allocation gVertexShaders;
35rs_allocation gRenderableObjects;
36
37rs_allocation gRenderPasses;
38
39// Temporary shaders
40rs_program_store gPFSBackground;
41
42uint32_t *gFrontToBack;
43static uint32_t gFrontToBackCount = 0;
44uint32_t *gBackToFront;
45static uint32_t gBackToFrontCount = 0;
46
47static SgCamera *gActiveCamera = NULL;
48
49static rs_allocation nullAlloc;
50
51// #define DEBUG_RENDERABLES
52static void draw(SgRenderable *obj) {
53#ifdef DEBUG_RENDERABLES
54    const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
55    rsDebug("**** Drawing object with transform", obj);
56    printName(objTransform->name);
57    rsDebug("Model matrix: ", &objTransform->globalMat);
58    printName(obj->name);
59#endif //DEBUG_RENDERABLES
60
61    const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
62    const SgVertexShader *pv = (const SgVertexShader *)rsGetElementAt(renderState->pv, 0);
63    const SgFragmentShader *pf = (const SgFragmentShader *)rsGetElementAt(renderState->pf, 0);
64
65    if (pv->objectConstIndex != -1) {
66        rsgBindConstant(pv->program, pv->objectConstIndex, obj->pv_const);
67    }
68    if (pf->objectConstIndex != -1) {
69        rsgBindConstant(pf->program, pf->objectConstIndex, obj->pf_const);
70    }
71
72    if (rsIsObject(renderState->ps)) {
73        rsgBindProgramStore(renderState->ps);
74    } else {
75        rsgBindProgramStore(gPFSBackground);
76    }
77
78    if (rsIsObject(renderState->pr)) {
79        rsgBindProgramRaster(renderState->pr);
80    } else {
81        rs_program_raster pr;
82        rsgBindProgramRaster(pr);
83    }
84
85    rsgBindProgramVertex(pv->program);
86    rsgBindProgramFragment(pf->program);
87
88    for (uint32_t i = 0; i < obj->pf_num_textures; i ++) {
89        const SgTexture *tex = rsGetElementAt(obj->pf_textures[i], 0);
90        rsgBindTexture(pf->program, i, tex->texture);
91    }
92
93    rsgDrawMesh(obj->mesh, obj->meshIndex);
94}
95
96static void sortToBucket(SgRenderable *obj) {
97    const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
98    if (rsIsObject(renderState->ps)) {
99        bool isOpaque = false;
100        if (isOpaque) {
101            gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
102        } else {
103            gBackToFront[gBackToFrontCount++] = (uint32_t)obj;
104        }
105    } else {
106        gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
107    }
108}
109
110static void updateActiveCamera(rs_allocation cam) {
111    gActiveCamera = (SgCamera *)rsGetElementAt(cam, 0);
112}
113
114static void prepareCameras() {
115    // now compute all the camera matrices
116    if (rsIsObject(gCameras)) {
117        float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
118        rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect));
119    }
120}
121
122static void prepareLights() {
123    if (rsIsObject(gLights)) {
124        rsForEach(gLightScript, gLights, nullAlloc);
125    }
126}
127
128static void drawSorted() {
129    for (int i = 0; i < gFrontToBackCount; i ++) {
130        SgRenderable *current = (SgRenderable*)gFrontToBack[i];
131        draw(current);
132    }
133
134    for (int i = 0; i < gBackToFrontCount; i ++) {
135        SgRenderable *current = (SgRenderable*)gBackToFront[i];
136        draw(current);
137    }
138}
139
140static void drawAllObjects(rs_allocation allObj) {
141    if (!rsIsObject(allObj)) {
142        return;
143    }
144
145    if (rsIsObject(gVertexShaders)) {
146        rsForEach(gVertexParamsScript, nullAlloc, gVertexShaders,
147                  gActiveCamera, sizeof(gActiveCamera));
148    }
149    if (rsIsObject(gFragmentShaders)) {
150        rsForEach(gFragmentParamsScript, nullAlloc, gFragmentShaders,
151                  gActiveCamera, sizeof(gActiveCamera));
152    }
153
154    // Run the params and cull script
155    rsForEach(gCullScript, nullAlloc, allObj, gActiveCamera, sizeof(gActiveCamera));
156    rsForEach(gObjectParamsScript, nullAlloc, allObj, gActiveCamera, sizeof(gActiveCamera));
157
158    int numRenderables = rsAllocationGetDimX(allObj);
159    for (int i = 0; i < numRenderables; i ++) {
160        rs_allocation *drawAlloc = (rs_allocation*)rsGetElementAt(allObj, i);
161        SgRenderable *current = (SgRenderable*)rsGetElementAt(*drawAlloc, 0);
162        if (current->isVisible) {
163            sortToBucket(current);
164        }
165    }
166    drawSorted();
167}
168
169int root(void) {
170#ifdef DEBUG_RENDERABLES
171    rsDebug("=============================================================================", 0);
172#endif // DEBUG_RENDERABLES
173
174    // first step is to update the transform hierachy
175    if (gRootNode && rsIsObject(gRootNode->children)) {
176        rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0);
177    }
178
179    prepareCameras();
180    prepareLights();
181
182    if (rsIsObject(gRenderPasses)) {
183        rsgClearDepth(1.0f);
184        int numPasses = rsAllocationGetDimX(gRenderPasses);
185        for (uint i = 0; i < numPasses; i ++) {
186            gFrontToBackCount = 0;
187            gBackToFrontCount = 0;
188            SgRenderPass *pass = (SgRenderPass*)rsGetElementAt(gRenderPasses, i);
189            if (rsIsObject(pass->color_target)) {
190                rsgBindColorTarget(pass->color_target, 0);
191            }
192            if (rsIsObject(pass->depth_target)) {
193                rsgBindDepthTarget(pass->depth_target);
194            }
195            if (!rsIsObject(pass->color_target) &&
196                !rsIsObject(pass->depth_target)) {
197                rsgClearAllRenderTargets();
198            }
199            updateActiveCamera(pass->camera);
200            if (pass->should_clear_color) {
201                rsgClearColor(pass->clear_color.x, pass->clear_color.y,
202                              pass->clear_color.z, pass->clear_color.w);
203            }
204            if (pass->should_clear_depth) {
205                rsgClearDepth(pass->clear_depth);
206            }
207            drawAllObjects(pass->objects);
208        }
209    } else {
210        gFrontToBackCount = 0;
211        gBackToFrontCount = 0;
212        rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
213        rsgClearDepth(1.0f);
214
215        if (rsIsObject(gCameras)) {
216            rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 0);
217            updateActiveCamera(*camAlloc);
218        }
219        drawAllObjects(gRenderableObjects);
220    }
221    return 10;
222}
223
224// Search through sorted and culled objects
225void pick(int screenX, int screenY) {
226    float3 pnt, vec;
227    getCameraRay(gActiveCamera, screenX, screenY, &pnt, &vec);
228
229    for (int i = 0; i < gFrontToBackCount; i ++) {
230        SgRenderable *current = (SgRenderable*)gFrontToBack[i];
231        bool isPicked = intersect(current, pnt, vec);
232        if (isPicked) {
233            current->cullType = CULL_ALWAYS;
234        }
235    }
236
237    for (int i = 0; i < gBackToFrontCount; i ++) {
238        SgRenderable *current = (SgRenderable*)gBackToFront[i];
239        bool isPicked = intersect(current, pnt, vec);
240        if (isPicked) {
241            current->cullType = CULL_ALWAYS;
242        }
243    }
244}
245