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