1/**
2 **
3 ** Copyright 2010, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18#include "src/pixelflinger2/pixelflinger2.h"
19
20#include <string.h>
21#include <stdio.h>
22
23void SetShaderVerifyFunctions(GGLInterface *);
24
25static void DepthFunc(GGLInterface * iface, GLenum func)
26{
27   GGL_GET_CONTEXT(ctx, iface);
28   if (GL_NEVER > func || GL_ALWAYS < func)
29      return gglError(GL_INVALID_ENUM);
30   ctx->state.bufferState.depthFunc = func & 0x7;
31   SetShaderVerifyFunctions(iface);
32}
33
34static void StencilFuncSeparate(GGLInterface * iface, GLenum face, GLenum func, GLint ref, GLuint mask)
35{
36   GGL_GET_CONTEXT(ctx, iface);
37   if (GL_FRONT > face || GL_FRONT_AND_BACK < face)
38      return gglError(GL_INVALID_ENUM);
39   if (GL_NEVER > func || GL_ALWAYS < func)
40      return gglError(GL_INVALID_ENUM);
41   mask &= 0xff;
42   ref = MAX2(MIN2(ref, 0xff), 0);
43   ref &= mask;
44   if (GL_FRONT == face || GL_FRONT_AND_BACK == face) {
45      ctx->state.frontStencil.ref = ref;
46      ctx->state.frontStencil.mask = mask;
47      ctx->state.frontStencil.func = func & 0x7;
48   }
49   if (GL_BACK == face || GL_FRONT_AND_BACK == face) {
50      ctx->state.backStencil.ref = ref;
51      ctx->state.backStencil.mask = mask;
52      ctx->state.backStencil.func = func & 0x7;
53   }
54   SetShaderVerifyFunctions(iface);
55}
56
57static unsigned StencilOpEnum(GLenum func, unsigned oldValue)
58{
59   switch (func) {
60   case GL_ZERO:
61      return 0;
62   case GL_KEEP: // fall through
63   case GL_REPLACE: // fall through
64   case GL_INCR: // fall through
65   case GL_DECR:
66      return func - GL_KEEP + 1;
67      break;
68   case GL_INVERT:
69      return 5;
70   case GL_INCR_WRAP:
71      return 6;
72   case GL_DECR_WRAP:
73      return 7;
74   default:
75      gglError(GL_INVALID_ENUM);
76      return oldValue;
77   }
78}
79
80static void StencilOpSeparate(GGLInterface * iface, GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
81{
82   GGL_GET_CONTEXT(ctx, iface);
83   if (GL_FRONT > face || GL_FRONT_AND_BACK < face)
84      return gglError(GL_INVALID_ENUM);
85   if (GL_FRONT == face || GL_FRONT_AND_BACK == face) {
86      ctx->state.frontStencil.sFail = StencilOpEnum(sfail, ctx->state.frontStencil.sFail);
87      ctx->state.frontStencil.dFail = StencilOpEnum(dpfail, ctx->state.frontStencil.dFail);
88      ctx->state.frontStencil.dPass = StencilOpEnum(dppass, ctx->state.frontStencil.dPass);
89   }
90   if (GL_BACK == face || GL_FRONT_AND_BACK == face) {
91      ctx->state.backStencil.sFail = StencilOpEnum(sfail, ctx->state.backStencil.sFail);
92      ctx->state.backStencil.dFail = StencilOpEnum(dpfail, ctx->state.backStencil.dFail);
93      ctx->state.backStencil.dPass = StencilOpEnum(dppass, ctx->state.backStencil.dPass);
94   }
95   SetShaderVerifyFunctions(iface);
96}
97
98static void StencilSelect(const GGLInterface * iface, GLenum face)
99{
100   GGL_GET_CONTEXT(ctx, iface);
101   if (GL_FRONT == face) {
102      ctx->activeStencil.face = 0;
103      ctx->activeStencil.ref = ctx->state.frontStencil.ref;
104      ctx->activeStencil.mask = ctx->state.frontStencil.mask;
105   } else if (GL_BACK == face) {
106      ctx->activeStencil.face = 1;
107      ctx->activeStencil.ref = ctx->state.backStencil.ref;
108      ctx->activeStencil.mask = ctx->state.backStencil.mask;
109   }
110}
111
112static void ClearStencil(GGLInterface * iface, GLint s)
113{
114   GGL_GET_CONTEXT(ctx, iface);
115   ctx->clearState.stencil = 0x01010101 * ((unsigned &)s & 0xff);
116}
117
118static void ClearColor(GGLInterface * iface, GLclampf r, GLclampf g, GLclampf b, GLclampf a)
119{
120   GGL_GET_CONTEXT(ctx, iface);
121   r = MAX2(MIN2(r, 1.0f), 0);
122   g = MAX2(MIN2(g, 1.0f), 0);
123   b = MAX2(MIN2(b, 1.0f), 0);
124   a = MAX2(MIN2(a, 1.0f), 0);
125   ctx->clearState.color = (unsigned(a * 255) << 24) | (unsigned(b * 255) << 16) |
126                           (unsigned(g * 255) << 8) | unsigned(r * 255);
127}
128
129static void ClearDepthf(GGLInterface * iface, GLclampf d)
130{
131   GGL_GET_CONTEXT(ctx, iface);
132   // assuming ieee 754 32 bit float and 32 bit 2's complement int
133   assert(sizeof(d) == sizeof(ctx->clearState.depth));
134   ctx->clearState.depth = (int &)d; // bit reinterpretation
135   if (0x80000000 & ctx->clearState.depth) // smaller negative float has bigger int representation, so flip
136      ctx->clearState.depth ^= 0x7fffffff; // since -FLT_MAX is close to -1 when bitcasted
137}
138
139static void Clear(const GGLInterface * iface, GLbitfield buf)
140{
141   GGL_GET_CONST_CONTEXT(ctx, iface);
142
143   // TODO DXL scissor test
144   if (GL_COLOR_BUFFER_BIT & buf && ctx->frameSurface.data) {
145      if (GGL_PIXEL_FORMAT_RGBA_8888 == ctx->frameSurface.format) {
146         unsigned * const end = (unsigned *)ctx->frameSurface.data +
147                                ctx->frameSurface.width * ctx->frameSurface.height;
148         const unsigned color = ctx->clearState.color;
149         for (unsigned * start = (unsigned *)ctx->frameSurface.data; start < end; start++)
150            *start = color;
151      } else if (GGL_PIXEL_FORMAT_RGB_565 == ctx->frameSurface.format) {
152         short * const end = (short *)ctx->frameSurface.data +
153                             ctx->frameSurface.width * ctx->frameSurface.height;
154         unsigned r = ctx->clearState.color & 0xf8, g = ctx->clearState.color & 0xfc00,
155                      b = ctx->clearState.color & 0xf80000;
156         const short color = (b >> 19) | (g >> 5) | (r >> 3);
157         for (short * start = (short *)ctx->frameSurface.data; start < end; start++)
158            *start = color;
159      } else
160         assert(0);
161   }
162   if (GL_DEPTH_BUFFER_BIT & buf && ctx->depthSurface.data) {
163      assert(GGL_PIXEL_FORMAT_Z_32 == ctx->depthSurface.format);
164      unsigned * const end = (unsigned *)ctx->depthSurface.data +
165                             ctx->depthSurface.width * ctx->depthSurface.height;
166      const unsigned depth = ctx->clearState.depth;
167      for (unsigned * start = (unsigned *)ctx->depthSurface.data; start < end; start++)
168         *start = depth;
169   }
170   if (GL_STENCIL_BUFFER_BIT & buf && ctx->stencilSurface.data) {
171      assert(GGL_PIXEL_FORMAT_S_8 == ctx->stencilSurface.format);
172      unsigned * const end = (unsigned *)((unsigned char *)ctx->stencilSurface.data +
173                                          ctx->stencilSurface.width * ctx->stencilSurface.height);
174      unsigned * start = (unsigned *)ctx->stencilSurface.data;
175      const unsigned stencil = ctx->clearState.stencil;
176      for (start; start < end; start++)
177         *start = stencil;
178      start--;
179      for (unsigned char * i = (unsigned char *)start; i < (unsigned char *)end; i++)
180         *i = stencil & 0xff;
181   }
182}
183
184static void SetBuffer(GGLInterface * iface, const GLenum type, GGLSurface * surface)
185{
186   GGL_GET_CONTEXT(ctx, iface);
187   bool changed = false;
188   if (GL_COLOR_BUFFER_BIT == type) {
189      if (surface) {
190         ctx->frameSurface = *surface;
191         changed |= ctx->frameSurface.format ^ surface->format;
192         switch (surface->format) {
193         case GGL_PIXEL_FORMAT_RGBA_8888:
194         case GGL_PIXEL_FORMAT_RGB_565:
195            break;
196         case GGL_PIXEL_FORMAT_RGBX_8888:
197         default:
198            LOGD("pf2: SetBuffer 0x%.04X format=0x%.02X \n", type, surface ? surface->format : 0);
199            assert(0);
200         }
201      } else {
202         memset(&ctx->frameSurface, 0, sizeof(ctx->frameSurface));
203         changed = true;
204      }
205      ctx->state.bufferState.colorFormat = ctx->frameSurface.format;
206   } else if (GL_DEPTH_BUFFER_BIT == type) {
207      if (surface) {
208         ctx->depthSurface = *surface;
209         changed |= ctx->depthSurface.format ^ surface->format;
210         assert(GGL_PIXEL_FORMAT_Z_32 == ctx->depthSurface.format);
211      } else {
212         memset(&ctx->depthSurface, 0, sizeof(ctx->depthSurface));
213         changed = true;
214      }
215      ctx->state.bufferState.depthFormat = ctx->depthSurface.format;
216   } else if (GL_STENCIL_BUFFER_BIT == type) {
217      if (surface) {
218         ctx->stencilSurface = *surface;
219         changed |= ctx->stencilSurface.format ^ surface->format;
220         assert(GGL_PIXEL_FORMAT_S_8 == ctx->stencilSurface.format);
221      } else {
222         memset(&ctx->stencilSurface, 0, sizeof(ctx->stencilSurface));
223         changed = true;
224      }
225      ctx->state.bufferState.stencilFormat = ctx->stencilSurface.format;
226   } else
227      gglError(GL_INVALID_ENUM);
228   if (changed) {
229      SetShaderVerifyFunctions(iface);
230   }
231}
232
233void InitializeBufferFunctions(GGLInterface * iface)
234{
235   iface->DepthFunc = DepthFunc;
236   iface->StencilFuncSeparate = StencilFuncSeparate;
237   iface->StencilOpSeparate = StencilOpSeparate;
238   iface->StencilSelect = StencilSelect;
239   iface->ClearStencil = ClearStencil;
240   iface->ClearColor = ClearColor;
241   iface->ClearDepthf = ClearDepthf;
242   iface->Clear = Clear;
243   iface->SetBuffer = SetBuffer;
244}
245