C++程序  |  277行  |  9.3 KB

/**
 **
 ** 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);
}