/**
**
** Copyright 2010, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include "pixelflinger2.h"
#include "src/talloc/hieralloc.h"
#include <string>
void gglError(unsigned error)
{
std::string str;
if (GL_NO_ERROR == error)
return;
ALOGD("\n*\n*\n pf2: gglError 0x%.4X \n*\n*\n", error);
assert(0);
}
static void DepthRangef(GGLInterface * iface, GLclampf zNear, GLclampf zFar)
{
GGL_GET_CONTEXT(ctx, iface);
ctx->viewport.n = VectorComp_t_CTR((zNear + zFar) / 2);
ctx->viewport.f = VectorComp_t_CTR((zFar - zNear) / 2);
}
static void Viewport(GGLInterface * iface, GLint x, GLint y, GLsizei width, GLsizei height)
{
GGL_GET_CONTEXT(ctx, iface);
ctx->viewport.x = VectorComp_t_CTR(x + width / 2);
ctx->viewport.y = VectorComp_t_CTR(y + height / 2);
ctx->viewport.w = VectorComp_t_CTR(width / 2);
ctx->viewport.h = VectorComp_t_CTR(height / 2);
}
static void CullFace(GGLInterface * iface, GLenum mode)
{
GGL_GET_CONTEXT(ctx, iface);
if (GL_FRONT > mode || GL_FRONT_AND_BACK < mode)
gglError(GL_INVALID_ENUM);
else
ctx->cullState.cullFace = mode - GL_FRONT;
}
static void FrontFace(GGLInterface * iface, GLenum mode)
{
GGL_GET_CONTEXT(ctx, iface);
if (GL_CW > mode || GL_CCW < mode)
gglError(GL_INVALID_ENUM);
else
ctx->cullState.frontFace = mode - GL_CW;
}
static void BlendColor(GGLInterface * iface, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
GGL_GET_CONTEXT(ctx, iface);
ctx->state.blendState.color[0] = MIN2(MAX2(red * 255, 0.0f), 255.0f);
ctx->state.blendState.color[1] = MIN2(MAX2(green * 255, 0.0f), 255.0f);
ctx->state.blendState.color[2] = MIN2(MAX2(blue * 255, 0.0f), 255.0f);
ctx->state.blendState.color[3] = MIN2(MAX2(alpha * 255, 0.0f), 255.0f);
SetShaderVerifyFunctions(iface);
}
static void BlendEquationSeparate(GGLInterface * iface, GLenum modeRGB, GLenum modeAlpha)
{
GGL_GET_CONTEXT(ctx, iface);
if (GL_FUNC_ADD != modeRGB && (GL_FUNC_SUBTRACT > modeRGB ||
GL_FUNC_REVERSE_SUBTRACT < modeRGB))
return gglError(GL_INVALID_ENUM);
if (GL_FUNC_ADD != modeRGB && (GL_FUNC_SUBTRACT > modeRGB ||
GL_FUNC_REVERSE_SUBTRACT < modeRGB))
return gglError(GL_INVALID_ENUM);
ctx->state.blendState.ce = (GGLBlendState::GGLBlendFunc)(modeRGB - GL_FUNC_ADD);
ctx->state.blendState.ae = (GGLBlendState::GGLBlendFunc)(modeAlpha - GL_FUNC_ADD);
SetShaderVerifyFunctions(iface);
}
static inline GGLBlendState::GGLBlendFactor GLBlendFactor(const GLenum factor)
{
#define SWITCH_LINE(c) case c: return GGLBlendState::G##c;
switch (factor)
{
SWITCH_LINE(GL_ZERO);
SWITCH_LINE(GL_ONE);
SWITCH_LINE(GL_SRC_COLOR);
SWITCH_LINE(GL_ONE_MINUS_SRC_COLOR);
SWITCH_LINE(GL_DST_COLOR);
SWITCH_LINE(GL_ONE_MINUS_DST_COLOR);
SWITCH_LINE(GL_SRC_ALPHA);
SWITCH_LINE(GL_ONE_MINUS_SRC_ALPHA);
SWITCH_LINE(GL_DST_ALPHA);
SWITCH_LINE(GL_ONE_MINUS_DST_ALPHA);
SWITCH_LINE(GL_SRC_ALPHA_SATURATE);
SWITCH_LINE(GL_CONSTANT_COLOR);
SWITCH_LINE(GL_ONE_MINUS_CONSTANT_COLOR);
SWITCH_LINE(GL_CONSTANT_ALPHA);
SWITCH_LINE(GL_ONE_MINUS_CONSTANT_ALPHA);
default: assert(0); return GGLBlendState::GGL_ZERO;
}
#undef SWITCH_LINE
}
static void BlendFuncSeparate(GGLInterface * iface, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
{
GGL_GET_CONTEXT(ctx, iface);
if (GL_ZERO != srcRGB && GL_ONE != srcRGB &&
(GL_SRC_COLOR > srcRGB || GL_SRC_ALPHA_SATURATE < srcRGB) &&
(GL_CONSTANT_COLOR > srcRGB || GL_ONE_MINUS_CONSTANT_ALPHA < srcRGB))
return gglError(GL_INVALID_ENUM);
if (GL_ZERO != srcAlpha && GL_ONE != srcAlpha &&
(GL_SRC_COLOR > srcAlpha || GL_SRC_ALPHA_SATURATE < srcAlpha) &&
(GL_CONSTANT_COLOR > dstRGB || GL_ONE_MINUS_CONSTANT_ALPHA < dstRGB))
return gglError(GL_INVALID_ENUM);
if (GL_ZERO != dstRGB && GL_ONE != dstRGB &&
(GL_SRC_COLOR > dstRGB || GL_ONE_MINUS_DST_COLOR < dstRGB) && // GL_SRC_ALPHA_SATURATE only for source
(GL_CONSTANT_COLOR > dstRGB || GL_ONE_MINUS_CONSTANT_ALPHA < dstRGB))
return gglError(GL_INVALID_ENUM);
if (GL_ZERO != dstAlpha && GL_ONE != dstAlpha &&
(GL_SRC_COLOR > dstAlpha || GL_ONE_MINUS_DST_COLOR < dstAlpha) &&
(GL_CONSTANT_COLOR > dstRGB || GL_ONE_MINUS_CONSTANT_ALPHA < dstRGB))
return gglError(GL_INVALID_ENUM);
if (srcAlpha == GL_SRC_ALPHA_SATURATE) // it's just 1 instead of min(sa, 1 - da) for alpha channel
srcAlpha = GL_ONE;
// in c++ it's templated function for color and alpha,
// so it requires setting srcAlpha to GL_ONE to run template again only for alpha
ctx->state.blendState.scf = GLBlendFactor(srcRGB);
ctx->state.blendState.saf = GLBlendFactor(srcAlpha);
ctx->state.blendState.dcf = GLBlendFactor(dstRGB);
ctx->state.blendState.daf = GLBlendFactor(dstAlpha);
SetShaderVerifyFunctions(iface);
}
static void EnableDisable(GGLInterface * iface, GLenum cap, GLboolean enable)
{
GGL_GET_CONTEXT(ctx, iface);
bool changed = false;
switch (cap) {
case GL_BLEND:
changed |= ctx->state.blendState.enable ^ enable;
ctx->state.blendState.enable = enable;
break;
case GL_CULL_FACE:
changed |= ctx->cullState.enable ^ enable;
ctx->cullState.enable = enable;
break;
case GL_DEPTH_TEST:
changed |= ctx->state.bufferState.depthTest ^ enable;
ctx->state.bufferState.depthTest = enable;
break;
case GL_STENCIL_TEST:
changed |= ctx->state.bufferState.stencilTest ^ enable;
ctx->state.bufferState.stencilTest = enable;
break;
case GL_DITHER:
// ALOGD("pf2: EnableDisable GL_DITHER \n");
break;
case GL_SCISSOR_TEST:
// ALOGD("pf2: EnableDisable GL_SCISSOR_TEST \n");
break;
case GL_TEXTURE_2D:
// ALOGD("pf2: EnableDisable GL_SCISSOR_TEST %d", enable);
break;
default:
ALOGD("pf2: EnableDisable 0x%.4X causes GL_INVALID_ENUM (maybe not implemented or ES 1.0) \n", cap);
// gglError(GL_INVALID_ENUM);
assert(0);
break;
}
if (changed)
SetShaderVerifyFunctions(iface);
}
void InitializeGGLState(GGLInterface * iface)
{
#if USE_DUAL_THREAD
reinterpret_cast<GGLContext *>(iface)->worker = GGLContext::Worker();
#endif
iface->DepthRangef = DepthRangef;
iface->Viewport = Viewport;
iface->CullFace = CullFace;
iface->FrontFace = FrontFace;
iface->BlendColor = BlendColor;
iface->BlendEquationSeparate = BlendEquationSeparate;
iface->BlendFuncSeparate = BlendFuncSeparate;
iface->EnableDisable = EnableDisable;
InitializeBufferFunctions(iface);
InitializeRasterFunctions(iface);
InitializeScanLineFunctions(iface);
InitializeShaderFunctions(iface);
InitializeTextureFunctions(iface);
iface->EnableDisable(iface, GL_DEPTH_TEST, false);
iface->DepthFunc(iface, GL_LESS);
iface->ClearColor(iface, 0, 0, 0, 0);
iface->ClearDepthf(iface, 1.0f);
iface->EnableDisable(iface, GL_STENCIL_TEST, false);
iface->StencilFuncSeparate(iface, GL_FRONT_AND_BACK, GL_ALWAYS, 0, 0xff);
iface->StencilOpSeparate(iface, GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
iface->FrontFace(iface, GL_CCW);
iface->CullFace(iface, GL_BACK);
iface->EnableDisable(iface, GL_CULL_FACE, false);
iface->EnableDisable(iface, GL_BLEND, false);
iface->BlendColor(iface, 0, 0, 0, 0);
iface->BlendEquationSeparate(iface, GL_FUNC_ADD, GL_FUNC_ADD);
iface->BlendFuncSeparate(iface, GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
iface->SetSampler(iface, i, NULL);
iface->SetBuffer(iface, GL_COLOR_BUFFER_BIT, NULL);
iface->SetBuffer(iface, GL_DEPTH_BUFFER_BIT, NULL);
iface->SetBuffer(iface, GL_STENCIL_BUFFER_BIT, NULL);
SetShaderVerifyFunctions(iface);
}
GGLInterface * CreateGGLInterface()
{
GGLContext * const ctx = (GGLContext *)calloc(1, sizeof(GGLContext));
if (!ctx)
return NULL;
assert((void *)ctx == (void *)&ctx->interface);
//_glapi_set_context(ctx->glCtx);
//_mesa_init_constants(&Const);
puts("InitializeGGLState");
InitializeGGLState(&ctx->interface);
return &ctx->interface;
}
void UninitializeGGLState(GGLInterface * iface)
{
#if USE_DUAL_THREAD
reinterpret_cast<GGLContext *>(iface)->worker.~Worker();
#endif
DestroyShaderFunctions(iface);
#if USE_LLVM_TEXTURE_SAMPLER
puts("USE_LLVM_TEXTURE_SAMPLER");
#endif
#if USE_LLVM_SCANLINE
puts("USE_LLVM_SCANLINE");
#endif
#if USE_LLVM_EXECUTIONENGINE
puts("USE_LLVM_EXECUTIONENGINE");
#endif
#if USE_DUAL_THREAD
puts("USE_DUAL_THREAD");
#endif
hieralloc_report_brief(NULL, stdout);
}
void DestroyGGLInterface(GGLInterface * iface)
{
GGLContext * const ctx = reinterpret_cast<GGLContext *>(iface);
UninitializeGGLState(iface);
free(ctx);
}