예제 #1
0
static SDL_bool
GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
{
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);

    if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
        GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
        GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
        GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
        GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
        GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
        return SDL_FALSE;
    }
    if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
        return SDL_FALSE;
    }
    if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
        return SDL_FALSE;
    }
    if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) {
        return SDL_FALSE;
    }
    return SDL_TRUE;
}
예제 #2
0
static void
GLES_SetBlendMode(GLES_RenderData * data, SDL_BlendMode blendMode)
{
    if (blendMode != data->current.blendMode) {
        if (blendMode == SDL_BLENDMODE_NONE) {
            data->glDisable(GL_BLEND);
        } else {
            data->glEnable(GL_BLEND);
            if (data->GL_OES_blend_func_separate_supported) {
                data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
                                             GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
                                             GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
                                             GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
            } else {
                data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
                                  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
            }
            if (data->GL_OES_blend_equation_separate_supported) {
                data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
                                                 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
            } else if (data->GL_OES_blend_subtract_supported) {
                data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
            }
        }
        data->current.blendMode = blendMode;
    }
}
예제 #3
0
void CG3DGraphicsGL::ApplySet(CG3DGlobalSet::SetType type)
{
	switch (type) {
		case CG3DGlobalSet::COLOUR: {
			CG3DColourSet* set = (CG3DColourSet*)m_Stacks[type].m_Value;

			if (set->m_DoClear)
				m_ClearEnabled |= GL_COLOR_BUFFER_BIT;
			else
				m_ClearEnabled &= ~GL_COLOR_BUFFER_BIT;
			
			CG3DVector4 cfloat = set->m_Clear.Get4f();
			glClearColor(cfloat.x, cfloat.y, cfloat.z, cfloat.w);
			
			glColorMask(set->m_UseR, set->m_UseG, set->m_UseB, set->m_UseA);
		} break;
		case CG3DGlobalSet::DEPTH: {
			CG3DDepthSet* set = (CG3DDepthSet*)m_Stacks[type].m_Value;

			if (set->m_DoClear)
				m_ClearEnabled |= GL_DEPTH_BUFFER_BIT;
			else
				m_ClearEnabled &= ~GL_DEPTH_BUFFER_BIT;
			
			glClearDepthf(set->m_Clear);
			
			glDepthMask(set->m_WriteDepth);

			switch (set->m_Test) {
				case CG3DDepthSet::ALWAYS: glDisable(GL_DEPTH_TEST); break;
				case CG3DDepthSet::NEVER: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_NEVER); break;
				case CG3DDepthSet::LESS: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); break;
				case CG3DDepthSet::LEQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); break;
				case CG3DDepthSet::EQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_EQUAL); break;
				case CG3DDepthSet::GREATER: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_GREATER); break;
				case CG3DDepthSet::GEQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_GEQUAL); break;
				case CG3DDepthSet::NOTEQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_NOTEQUAL); break;
			}
		} break;
		case CG3DGlobalSet::STENCIL: {
			CG3DStencilSet* set = (CG3DStencilSet*)m_Stacks[type].m_Value;

			if (set->m_DoClear)
				m_ClearEnabled |= GL_STENCIL_BUFFER_BIT;
			else
				m_ClearEnabled &= ~GL_STENCIL_BUFFER_BIT;
			
			glClearStencil(set->m_Clear);

			ApplyStencil(set);
		} break;
		case CG3DGlobalSet::CULL: {
			CG3DCullSet* set = (CG3DCullSet*)m_Stacks[type].m_Value;

			switch (set->m_Cull) {
				case CG3DCullSet::CULL_NONE: glDisable(GL_CULL_FACE); break;
				case CG3DCullSet::CULL_FRONT: glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); break;
				case CG3DCullSet::CULL_BACK: glEnable(GL_CULL_FACE); glCullFace(GL_BACK); break;
			}

			//if (set->m_FrontIsCCW != CG3DCullSet::NO)
				glFrontFace(GL_CCW);
			//else
			//	glFrontFace(GL_CW);
		} break;
		case CG3DGlobalSet::VIEWPORT: {
			CG3DViewportSet* set = (CG3DViewportSet*)m_Stacks[type].m_Value;
			
			glViewport((int)set->m_Rect.x, (int)set->m_Rect.y, (int)set->m_Rect.z, (int)set->m_Rect.w);

			glDepthRangef(set->m_NearZ, set->m_FarZ);
		} break;
		case CG3DGlobalSet::SCISSOR: {
			CG3DScissorSet* set = (CG3DScissorSet*)m_Stacks[type].m_Value;

			if (set->m_Do)
				glEnable(GL_SCISSOR_TEST);
			else
				glDisable(GL_SCISSOR_TEST);
			
			glScissor((int)set->m_Rect.x, (int)set->m_Rect.y, (int)set->m_Rect.z, (int)set->m_Rect.w);
		} break;
		case CG3DGlobalSet::BLEND: {
			CG3DBlendSet* set = (CG3DBlendSet*)m_Stacks[type].m_Value;
			CG3DVector4 col = set->m_Colour.Get4f();

			switch (set->m_Mode)
			{
				case CG3DBlendSet::OFF:
					glDisable(GL_BLEND);
					break;
				case CG3DBlendSet::COMBINED:
					glEnable(GL_BLEND);
					glBlendEquation(GetBlendFunc(set->m_Func));
					glBlendFunc(GetBlendParam(set->m_Src), GetBlendParam(set->m_Dest));
					glBlendColor(col.x, col.y, col.z, col.w);
					break;
				case CG3DBlendSet::SEPARATE:
					glEnable(GL_BLEND);
					glBlendEquationSeparate(GetBlendFunc(set->m_Func), GetBlendFunc(set->m_FuncAlpha));
					glBlendFuncSeparate(GetBlendParam(set->m_Src), GetBlendParam(set->m_Dest), GetBlendParam(set->m_SrcAlpha), GetBlendParam(set->m_DestAlpha));
					glBlendColor(col.x, col.y, col.z, col.w);
					break;
			}
		} break;
		case CG3DGlobalSet::SAMPLE_COVERAGE: {
			CG3DSampleCoverageSet* set = (CG3DSampleCoverageSet*)m_Stacks[type].m_Value;

			if (set->m_Coverage)
				glEnable(GL_SAMPLE_COVERAGE);
			else
				glDisable(GL_SAMPLE_COVERAGE);
			
			if (set->m_AlphaCoverage)
				glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
			else
				glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
			glSampleCoverage(set->m_Value, set->m_Invert);
		} break;
		case CG3DGlobalSet::DITHER: {
			CG3DDitherSet* set = (CG3DDitherSet*)m_Stacks[type].m_Value;

			if (set->m_Dither)
				glEnable(GL_DITHER);
			else
				glDisable(GL_DITHER);
		} break;
		case CG3DGlobalSet::POLYGON_OFFSET: {
			CG3DPolygonOffsetSet* set = (CG3DPolygonOffsetSet*)m_Stacks[type].m_Value;

			if (set->m_PolygonOffset)
				glEnable(GL_POLYGON_OFFSET_FILL);
			else
				glDisable(GL_POLYGON_OFFSET_FILL);

			glPolygonOffset(set->m_Factor, set->m_Units);
		} break;
	}
}
예제 #4
0
bool LWFRendererFactory::Render(class LWF *lwf, Node *node,
	BlendEquationProtocol *be, int renderingIndex, bool visible,
	BlendFunc *baseBlendFunc)
{
	m_renderingIndex = renderingIndex;

	node->setVisible(visible);
	if (!visible)
		return false;

	Node *target;
	switch (m_maskMode) {
	case Format::BLEND_MODE_ERASE:
	case Format::BLEND_MODE_MASK:
	case Format::BLEND_MODE_LAYER:
		{
			LWFMask *mask;
			if (m_lastMaskMode != m_maskMode) {
				++m_maskNo;
				if (m_masks.size() > m_maskNo) {
					mask = m_masks[m_maskNo];
				} else {
					mask = LWFMask::create();
					m_masks.push_back(mask);
				}
				PlaceNode(m_node, mask);

				LWFMask *layer = nullptr;
				if (m_lastMaskMode == Format::BLEND_MODE_LAYER &&
						(m_maskMode == Format::BLEND_MODE_ERASE ||
							m_maskMode == Format::BLEND_MODE_MASK) &&
						m_maskNo > 0) {
					layer = m_masks[m_maskNo - 1];
					if (layer)
						layer->setLocalZOrder(INT_MAX);
					PlaceNode(mask, layer);
				}

				if (layer && mask) {
					switch (m_maskMode) {
					case Format::BLEND_MODE_ERASE:
					case Format::BLEND_MODE_MASK:
						switch (m_maskMode) {
						case Format::BLEND_MODE_ERASE:
							layer->setBlendFunc(
								{GL_ONE_MINUS_DST_ALPHA, GL_ZERO});
							break;
						case Format::BLEND_MODE_MASK:
							layer->setBlendFunc(
								{GL_DST_ALPHA, GL_ZERO});
							break;
						}
						BlendFunc blendFunc = {GL_ONE, GL_ZERO};
						GetBlendFunc(blendFunc, m_blendMode);
						mask->setBlendFunc(blendFunc);
						break;
					}
				}

				m_lastMaskMode = m_maskMode;
			} else {
				mask = m_masks[m_maskNo];
			}
			if (mask)
				mask->setLocalZOrder(m_renderingIndex + 1);
			target = mask;

		}
		break;

	default:
		target = m_node;
		break;
	}

	PlaceNode(target, node);

	node->setLocalZOrder(renderingIndex);

	BlendProtocol *p = dynamic_cast<BlendProtocol *>(node);
	if (p) {
		BlendFunc blendFunc =
			baseBlendFunc ? *baseBlendFunc : p->getBlendFunc();
		GetBlendFunc(blendFunc, m_blendMode);
		p->setBlendFunc(blendFunc);
	}

	BlendEquationProtocol *ep = dynamic_cast<BlendEquationProtocol *>(node);
	if (ep)
		ep->setBlendEquation(m_blendMode);

	return true;
}
예제 #5
0
  void WalkEdges(const GEdge e1, const GEdge e2, const GPaint &paint) {

    const GBitmap &bm = GetInternalBitmap();
    int h = bm.fHeight;
    int w = bm.fWidth;

    GASSERT(e1.p1.y() == e2.p1.y());
    int startY = Clamp(static_cast<int>(e1.p1.y() + 0.5f), 0, h-1);
    GASSERT(e1.p2.y() == e2.p2.y());
    int endY = Clamp(static_cast<int>(e1.p2.y() + 0.5f), 0, h-1);

    if(endY == startY) {
      return;
    }

    GASSERT(endY > startY);

    // Initialize to NAN
    float m1 = 0.0f/0.0f, b1;
    float m2 = 0.0f/0.0f, b2;
    bool vert1 = e1.ComputeLine(m1, b1);
    bool vert2 = e2.ComputeLine(m2, b2);

    if(m1 == 0 || m2 == 0) {
      return;
    }

    // Collinear?
    if(vert2 && vert1 && e1.p1.x() == e2.p1.x()) {
      return;
    } else if(m1 == m2 && b1 == b2) {
      return;
    }

    float stepX1 = vert1? 0 : 1/m1;
    float stepX2 = vert2? 0 : 1/m2;

    GPoint p1, p2;
    float sY = static_cast<float>(startY) + 0.5f;
    if(vert1) {
      p1.set(e1.p1.x(), sY);
    } else {
      p1.set((sY - b1) / m1, sY);
    }

    if(vert2) {
      p2.set(e2.p1.x(), sY);
    } else {
      p2.set((sY - b2) / m2, sY);
    }

    // Make sure that p1 is always less than p2 to avoid
    // doing a min/max in the inner loop
    if(p1.x() > p2.x()) {
      std::swap(p1, p2);
      std::swap(stepX1, stepX2);
    }

    GPixel color = ColorToPixel(paint.getColor());
    BlendFunc blend = GetBlendFunc(eBlendOp_SrcOver);

    uint32_t nSteps = endY - startY;
    for(uint32_t i = 0; i < nSteps; i++) {

      // Since we haven't implemented clipping yet, take care
      // not to go beyond our bounds...
      const int x1 = Clamp<int>(p1.fX + 0.5f, 0, w-1);
      const int x2 = Clamp<int>(p2.fX + 0.5f, 0, w-1);

      GPixel *row = GetRow(bm, startY + i);
      for(int x = x1; x < x2; x++) {
        row[x] = blend(row[x], color);
      }

      p1.fX += stepX1;
      p2.fX += stepX2;
    }
  }
예제 #6
0
  void fillIRect(const GIRect &rect, const GColor &c, EBlendOp op) {

    const GBitmap &bitmap = GetInternalBitmap();

    uint32_t h = bitmap.fHeight;
    uint32_t w = bitmap.fWidth;

    GIRect bmRect;
    if(!(bmRect.setIntersection(rect, GIRect::MakeWH(w, h))))
      return;

    h = bmRect.height();
    w = bmRect.width();

    // premultiply alpha ...
    GPixel clearValue = ColorToPixel(c);

    // Figure out blendfunc
    BlendFunc blend = GetBlendFunc(op);

    if(bitmap.fRowBytes == w * sizeof(GPixel)) {
      GPixel *p = bitmap.fPixels + bmRect.fTop*bitmap.fWidth + bmRect.fLeft;
      switch(op) {
        case eBlendOp_Src:
          memsetPixel(p, clearValue, w*h);
          break;

        default: {
          GPixel *end = bitmap.fPixels + ((bmRect.fBottom - 1) * w + bmRect.fRight);
          for(; p != end; p++) {
            *p = blend(*p, clearValue);
          }
          break;
        }
      }

    } else {
      
      for(uint32_t j = bmRect.fTop; j < bmRect.fBottom; j++) {
        GPixel *rowPixels = GetRow(bitmap, j) + bmRect.fLeft;

        switch(op) {
          case eBlendOp_Src: {
            memsetPixel(rowPixels, clearValue, w);
            break;
          }

          default: {
            GPixel oldP = rowPixels[0];
            GPixel newP = blend(oldP, clearValue);
            rowPixels[0] = newP;
            
            for(uint32_t i = 1; i < w; i++) {
              if(oldP == rowPixels[i]) {
                rowPixels[i] = newP;
              } else {
                oldP = rowPixels[i];
                newP = rowPixels[i] = blend(rowPixels[i], clearValue);
              }
            }
            break;
          }
        }  // switch
      }  // for
    }  // else
  }