diff --git a/project/Build.xml b/project/Build.xml index 41d4a5f0a..fd6d3dde0 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -357,7 +357,7 @@ - + diff --git a/project/include/Display.h b/project/include/Display.h index d2b39ff2d..b5571851b 100644 --- a/project/include/Display.h +++ b/project/include/Display.h @@ -436,6 +436,8 @@ public: virtual bool getMultitouchSupported() { return false; } virtual void setMultitouchActive(bool inActive) { } virtual bool getMultitouchActive() { return false; } + + virtual uint32 getBackgroundMask() { return 0xffffffff; } Matrix GetFullMatrix(bool inStageScaling); bool FinishEditOnEnter(); diff --git a/project/include/Graphics.h b/project/include/Graphics.h index f64829063..7e2eb0fb2 100644 --- a/project/include/Graphics.h +++ b/project/include/Graphics.h @@ -456,84 +456,10 @@ struct RenderState }; -void ResetHardwareContext(); +class HardwareData; +class HardwareContext; - -enum PrimType { ptTriangleFan, ptTriangleStrip, ptTriangles, ptLineStrip, ptPoints, ptLines }; - -struct DrawElement -{ - uint8 mPrimType; - bool mBitmapRepeat; - bool mBitmapSmooth; - int mFirst; - int mCount; - uint32 mColour; - float mWidth; - StrokeScaleMode mScaleMode; -}; - -typedef QuickVec DrawElements; -typedef QuickVec Vertices; -typedef QuickVec TexCoords; -typedef QuickVec Colours; - -void ReleaseVertexBufferObject(unsigned int inVBO); - -void ConvertOutlineToTriangles(Vertices &ioOutline,const QuickVec &inSubPolys); - -struct HardwareArrays -{ - enum - { - BM_ADD = 0x00000001, - PERSPECTIVE = 0x00000002, - RADIAL = 0x00000004, - BM_MULTIPLY = 0x00000008, - BM_SCREEN = 0x00000010, - - AM_PREMULTIPLIED = 0x00000100, - - FOCAL_MASK = 0x0000ff00, - FOCAL_SIGN = 0x00010000, - }; - - HardwareArrays(Surface *inSurface,unsigned int inFlags); - ~HardwareArrays(); - bool ColourMatch(bool inWantColour); - - - DrawElements mElements; - Vertices mVertices; - TexCoords mTexCoords; - Colours mColours; - Surface *mSurface; - unsigned int mFlags; - //unsigned int mVertexBO; -}; - -typedef QuickVec HardwareCalls; - -class HardwareData -{ -public: - ~HardwareData(); - - HardwareArrays &GetArrays(Surface *inSurface,bool inWithColour,unsigned int inFlags); - - HardwareCalls mCalls; - -}; - - - - -extern HardwareContext *gDirectRenderContext; - -void BuildHardwareJob(const class GraphicsJob &inJob,const GraphicsPath &inPath, - HardwareData &ioData, HardwareContext &inHardware); - int UpToPower2(int inX); inline int IsPower2(unsigned int inX) { return (inX & (inX-1))==0; } diff --git a/project/include/Hardware.h b/project/include/Hardware.h new file mode 100644 index 000000000..6c21513da --- /dev/null +++ b/project/include/Hardware.h @@ -0,0 +1,89 @@ +#ifndef LIME_HARDWARE_H +#define LIME_HARDWARE_H + +#include "Graphics.h" + +namespace lime +{ + +void ResetHardwareContext(); + +typedef QuickVec Vertices; + +enum PrimType { ptTriangleFan, ptTriangleStrip, ptTriangles, ptLineStrip, ptPoints, ptLines }; + +enum +{ + DRAW_HAS_COLOUR = 0x00000001, + DRAW_HAS_NORMAL = 0x00000002, + DRAW_HAS_PERSPECTIVE = 0x00000004, + DRAW_RADIAL = 0x00000008, + + DRAW_HAS_TEX = 0x00000010, + DRAW_BMP_REPEAT = 0x00000020, + DRAW_BMP_SMOOTH = 0x00000040, +}; + + + + +struct DrawElement +{ + uint8 mFlags; + uint8 mPrimType; + uint8 mBlendMode; + uint8 mScaleMode; + short mRadialPos; + + uint8 mStride; + int mCount; + + int mVertexOffset; + int mTexOffset; + int mColourOffset; + int mNormalOffset; + + uint32 mColour; + Surface *mSurface; + + // For ptLineStrip/ptLines + float mWidth; + +}; + +typedef QuickVec DrawElements; + +class HardwareData +{ +public: + HardwareData(); + ~HardwareData(); + + void releaseVbo(); + float scaleOf(const RenderState &inState) const; + bool isScaleOk(const RenderState &inState) const; + void clear(); + + DrawElements mElements; + QuickVec mArray; + float mMinScale; + float mMaxScale; + + mutable HardwareContext *mVboOwner; + mutable int mRendersWithoutVbo; + mutable unsigned int mVertexBo; + mutable int mContextId; +}; + + +void ConvertOutlineToTriangles(Vertices &ioOutline,const QuickVec &inSubPolys); + +extern HardwareContext *gDirectRenderContext; + +void BuildHardwareJob(const class GraphicsJob &inJob,const GraphicsPath &inPath, + HardwareData &ioData, HardwareContext &inHardware,const RenderState &inState); + + +} + +#endif diff --git a/project/include/Pixel.h b/project/include/Pixel.h index cc8ccddce..4328135bb 100644 --- a/project/include/Pixel.h +++ b/project/include/Pixel.h @@ -27,14 +27,6 @@ enum PixelFormat pfSwapRB = 0x02, }; -enum AlphaMode -{ - amUnknown = 0x00, - amPremultiplied = 0x01, - amStraight = 0x02, - amIgnore = 0x03, -}; - typedef unsigned char Uint8; diff --git a/project/include/renderer/common/HardwareContext.h b/project/include/renderer/common/HardwareContext.h index d4a6e9310..9f9e292cb 100644 --- a/project/include/renderer/common/HardwareContext.h +++ b/project/include/renderer/common/HardwareContext.h @@ -23,12 +23,13 @@ namespace lime { virtual void Clear (uint32 inColour, const Rect *inRect = 0) = 0; virtual class Texture *CreateTexture (class Surface *inSurface, unsigned int inFlags) = 0; virtual void DestroyNativeTexture (void *inNativeTexture) = 0; + virtual void DestroyVbo (unsigned int inVbo) = 0; virtual void EndBitmapRender () = 0; virtual void EndRender () = 0; virtual void Flip () = 0; virtual int Height () const = 0; - virtual bool Hits (const RenderState &inState, const HardwareCalls &inCalls); - virtual void Render (const RenderState &inState, const HardwareCalls &inCalls) = 0; + virtual bool Hits (const RenderState &inState, const HardwareData &inData); + virtual void Render (const RenderState &inState, const HardwareData &inData) = 0; virtual void RenderBitmap (const Rect &inSrc, int inX, int inY) = 0; virtual void SetQuality (StageQuality inQuality) = 0; virtual void SetViewport (const Rect &inRect) = 0; @@ -41,4 +42,4 @@ namespace lime { }; -#endif \ No newline at end of file +#endif diff --git a/project/include/renderer/common/HardwareSurface.h b/project/include/renderer/common/HardwareSurface.h index df3bc0bdf..8f7b53b20 100644 --- a/project/include/renderer/common/HardwareSurface.h +++ b/project/include/renderer/common/HardwareSurface.h @@ -21,7 +21,6 @@ namespace lime { void Clear (uint32 inColour, const Rect *inRect = 0) { mHardware->Clear (inColour, inRect); } void EndRender () { mHardware->EndRender (); } PixelFormat Format () const { return pfHardware; } - AlphaMode GetAlphaMode () const { return mAlphaMode; } const uint8 *GetBase () const { return 0; } int GetStride () const { return 0; } int Height () const { return mHardware->Height (); } @@ -38,7 +37,6 @@ namespace lime { private: - AlphaMode mAlphaMode; HardwareContext *mHardware; }; diff --git a/project/include/renderer/common/SimpleSurface.h b/project/include/renderer/common/SimpleSurface.h index dc4dcb140..846fb0239 100644 --- a/project/include/renderer/common/SimpleSurface.h +++ b/project/include/renderer/common/SimpleSurface.h @@ -19,7 +19,6 @@ namespace lime { virtual void colorTransform (const Rect &inRect, ColorTransform &inTransform); virtual void StretchTo (const RenderTarget &outTarget, const Rect &inSrcRect, const DRect &inDestRect) const; - virtual void setAlphaMode (AlphaMode am) { mAlphaMode = am; } virtual void setGPUFormat (PixelFormat pf) { mGPUPixelFormat = pf; } void applyFilter (Surface *inSrc, const Rect &inRect, ImagePoint inOffset, Filter *inFilter); @@ -43,7 +42,6 @@ namespace lime { void Zero (); PixelFormat Format () const { return mPixelFormat; } - AlphaMode GetAlphaMode () const { return mAlphaMode; } const uint8 *GetBase () const { return mBase; } int GetStride () const { return mStride; } int GPUFormat () const { return mGPUPixelFormat; } @@ -54,7 +52,6 @@ namespace lime { ~SimpleSurface (); - AlphaMode mAlphaMode; uint8 *mBase; int mGPUPixelFormat; int mHeight; diff --git a/project/include/renderer/common/Surface.h b/project/include/renderer/common/Surface.h index 03673f6ec..126d59a1c 100644 --- a/project/include/renderer/common/Surface.h +++ b/project/include/renderer/common/Surface.h @@ -7,6 +7,7 @@ #include #include "renderer/common/Texture.h" #include "renderer/common/HardwareContext.h" +#include namespace lime { @@ -28,7 +29,6 @@ namespace lime { virtual void Clear (uint32 inColour, const Rect *inRect = 0) = 0; virtual void EndRender () = 0; virtual PixelFormat Format () const = 0; - virtual AlphaMode GetAlphaMode () const = 0; virtual const uint8 *GetBase () const = 0; virtual int GetStride () const = 0; virtual int Height () const = 0; @@ -49,7 +49,6 @@ namespace lime { virtual int GPUFormat () const { return Format (); } virtual void multiplyAlpha () {} virtual void noise (unsigned int randomSeed, unsigned int low, unsigned int high, int channelOptions, bool grayScale) {} - virtual void setAlphaMode (AlphaMode am) {} virtual void SetAllowTrans (bool inAllowTrans) { mAllowTrans = inAllowTrans; } virtual void SetFlags (unsigned int inFlags) { mFlags = inFlags; } virtual void setGPUFormat (PixelFormat pf) {} diff --git a/project/include/renderer/opengl/OGL.h b/project/include/renderer/opengl/OGL.h index 8048b4f41..842d5dea1 100644 --- a/project/include/renderer/opengl/OGL.h +++ b/project/include/renderer/opengl/OGL.h @@ -200,20 +200,18 @@ namespace lime Texture *OGLCreateTexture(Surface *inSurface,unsigned int inFlags); -enum GPUProgID +enum { - gpuNone = -1, - gpuSolid, - gpuColour, - gpuColourTransform, - gpuTexture, - gpuTextureColourArray, - gpuTextureTransform, - gpuBitmap, - gpuBitmapAlpha, - gpuRadialGradient, - gpuRadialFocusGradient, - gpuSIZE, + PROG_TEXTURE = 0x0001, + PROG_ALPHA_TEXTURE = 0x0002, + PROG_COLOUR_PER_VERTEX = 0x0004, + PROG_NORMAL_DATA = 0x0008, + PROG_RADIAL = 0x0010, + PROG_RADIAL_FOCUS = 0x0020, + PROG_TINT = 0x0040, + PROG_COLOUR_OFFSET = 0x0080, + + PROG_COUNT = 0x0100, }; typedef float Trans4x4[4][4]; @@ -221,22 +219,22 @@ typedef float Trans4x4[4][4]; class GPUProg { public: - static GPUProg *create(GPUProgID inID, AlphaMode inAlphaMode); + static GPUProg *create(unsigned int inID); virtual ~GPUProg() {} virtual bool bind() = 0; - virtual void setPositionData(const float *inData, bool inIsPerspective) = 0; - virtual void setTexCoordData(const float *inData) = 0; - virtual void setColourData(const int *inData) = 0; - virtual void setColourTransform(const ColorTransform *inTransform) = 0; - virtual int getTextureSlot() = 0; - + virtual void disableSlots() = 0; virtual void setTransform(const Trans4x4 &inTrans) = 0; - virtual void setTint(unsigned int inColour) = 0; + virtual void setColourTransform(const ColorTransform *inTransform, unsigned int inColour) = 0; virtual void setGradientFocus(float inFocus) = 0; - virtual void finishDrawing() = 0; + + int vertexSlot; + int textureSlot; + int normalSlot; + int colourSlot; + }; void InitOGL2Extensions(); diff --git a/project/include/renderer/opengl/OpenGL2Context.h b/project/include/renderer/opengl/OpenGL2Context.h deleted file mode 100644 index f081e586d..000000000 --- a/project/include/renderer/opengl/OpenGL2Context.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef RENDERER_OPENGL2_CONTEXT_H -#define RENDERER_OPENGL2_CONTEXT_H - - -#include "OpenGLContext.h" - - -namespace lime { - - - class OpenGL2Context : public OpenGLContext { - - public: - - OpenGL2Context (WinDC inDC, GLCtx inOGLCtx); - ~OpenGL2Context (); - - virtual void CombineModelView (const Matrix &inModelView); - virtual void FinishBitmapRender (); - virtual void FinishDrawing (); - virtual void OnBeginRender (); - virtual void PopBitmapMatrix (); - virtual void PrepareBitmapRender (); - virtual bool PrepareDrawing (); - virtual void PushBitmapMatrix (); - virtual void SetBitmapData (const float *inPos, const float *inTex); - virtual void SetColourArray (const int *inData); - virtual void SetModulatingTransform (const ColorTransform *inTransform); - virtual void setOrtho (float x0, float x1, float y0, float y1); - virtual void SetPositionData (const float *inData, bool inPerspective); - virtual void SetRadialGradient (bool inIsRadial, float inFocus); - virtual void SetSolidColour (unsigned int col); - virtual void SetTexture (Surface *inSurface, const float *inTexCoords); - - Trans4x4 mBitmapTrans; - const int *mColourArray; - GPUProg *mCurrentProg; - const ColorTransform *mColourTransform; - bool mIsRadial; - double mOffsetX; - double mOffsetY; - const float *mPosition; - bool mPositionPerspective; - GPUProg *mProg[gpuSIZE]; - float mRadialFocus; - double mScaleX; - double mScaleY; - const float *mTexCoords; - Surface *mTextureSurface; - Trans4x4 mTrans; - - }; - - -} - - -#endif diff --git a/project/include/renderer/opengl/OpenGLContext.h b/project/include/renderer/opengl/OpenGLContext.h index 55d86f731..079b0663c 100644 --- a/project/include/renderer/opengl/OpenGLContext.h +++ b/project/include/renderer/opengl/OpenGLContext.h @@ -17,34 +17,21 @@ namespace lime { OpenGLContext (WinDC inDC, GLCtx inOGLCtx); ~OpenGLContext (); - virtual void CombineModelView (const Matrix &inModelView); - virtual void FinishDrawing (); - virtual void FinishBitmapRender (); - virtual void OnBeginRender (); - virtual void PopBitmapMatrix (); - virtual void PrepareBitmapRender (); - virtual bool PrepareDrawing (); - virtual void PushBitmapMatrix (); - virtual void SetBitmapData (const float *inPos, const float *inTex); - virtual void SetColourArray (const int *inData); - virtual void SetModulatingTransform (const ColorTransform *inTransform); - virtual void setOrtho (float x0,float x1, float y0, float y1); - virtual void SetPositionData (const float *inData, bool inPerspective); - virtual void SetRadialGradient (bool inIsRadial, float inFocus); - virtual void SetSolidColour (unsigned int col); - virtual void SetTexture (Surface *inSurface, const float *inTexCoords); - void BeginBitmapRender (Surface *inSurface, uint32 inTint, bool inRepeat, bool inSmooth); void BeginRender (const Rect &inRect, bool inForHitTest); void Clear (uint32 inColour, const Rect *inRect); + void CombineModelView (const Matrix &inModelView); Texture *CreateTexture (Surface *inSurface, unsigned int inFlags); void DestroyNativeTexture (void *inNativeTexture); + void DestroyVbo (unsigned int inVbo); void EndBitmapRender (); void EndRender (); void Flip (); - void Render (const RenderState &inState, const HardwareCalls &inCalls); + void Render (const RenderState &inState, const HardwareData &inData); void RenderBitmap (const Rect &inSrc, int inX, int inY); + void RenderData (const HardwareData &inData, const ColorTransform *ctrans, const Trans4x4 &inTrans); void SetLineWidth (double inWidth); + void setOrtho (float x0, float x1, float y0, float y1); void SetQuality (StageQuality inQ); void SetViewport (const Rect &inRect); void SetWindowSize (int inWidth, int inHeight); @@ -52,10 +39,9 @@ namespace lime { int Height () const { return mHeight; } int Width () const { return mWidth; } - AlphaMode mAlphaMode; - Surface *mBitmapSurface; + HardwareData mBitmapBuffer; Texture *mBitmapTexture; - bool mColourArrayEnabled; + Trans4x4 mBitmapTrans; WinDC mDC; int mHeight; double mLineScaleH; @@ -63,21 +49,25 @@ namespace lime { double mLineScaleV; double mLineWidth; Matrix mModelView; + double mOffsetX; + double mOffsetY; GLCtx mOGLCtx; - bool mPointSmooth; - bool mPointsToo; + GPUProg *mProg[PROG_COUNT]; StageQuality mQuality; + double mScaleX; + double mScaleY; ThreadId mThreadId; - uint32 mTint; - bool mUsingBitmapMatrix; + Trans4x4 mTrans; Rect mViewport; int mWidth; QuickVec mZombieTextures; - + QuickVec mZombieVbos; + }; const double one_on_255 = 1.0 / 255.0; + const double one_on_256 = 1.0 / 256.0; static GLuint sgOpenglType[] = { GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, GL_TRIANGLES, GL_LINE_STRIP, GL_POINTS, GL_LINES }; diff --git a/project/include/renderer/opengl/OpenGLProgram.h b/project/include/renderer/opengl/OpenGLProgram.h index a51228aec..1e6d5ffcf 100644 --- a/project/include/renderer/opengl/OpenGLProgram.h +++ b/project/include/renderer/opengl/OpenGLProgram.h @@ -12,24 +12,19 @@ namespace lime { public: - OpenGLProgram (const char *inVertProg, const char *inFragProg, AlphaMode inAlphaMode); + OpenGLProgram (const std::string &inVertProg, const std::string &inFragProg); virtual ~OpenGLProgram (); virtual bool bind (); virtual void setGradientFocus (float inFocus); GLuint createShader (GLuint inType, const char *inShader); - void finishDrawing (); + void disableSlots (); int getTextureSlot (); void recreate (); - void setColourData (const int *inData); - void setColourTransform (const ColorTransform *inTransform); - void setPositionData (const float *inData, bool inIsPerspective); - void setTexCoordData (const float *inData); - void setTint (unsigned int inColour); + void setColourTransform (const ColorTransform *inTransform, unsigned int inColour); void setTransform (const Trans4x4 &inTrans); - AlphaMode mAlphaMode; GLint mASlot; GLint mColourArraySlot; GLint mColourOffsetSlot; @@ -37,17 +32,19 @@ namespace lime { const ColorTransform *mColourTransform; int mContextVersion; GLuint mFragId; - const char *mFragProg; + std::string mFragProg; GLint mFXSlot; + GLint mImageSlot; GLint mOn2ASlot; GLuint mProgramId; - GLint mTexCoordSlot; - GLint mTextureSlot; - GLint mTintSlot; GLint mTransformSlot; GLuint mVertId; - const char *mVertProg; - GLint mVertexSlot; + std::string mVertProg; + + //GLint colourSlot; + //GLint normalSlot; + //GLint textureSlot; + //GLint vertexSlot; }; diff --git a/project/src/backend/sdl/SDLStage.cpp b/project/src/backend/sdl/SDLStage.cpp index aa1b18e15..b9b66b76d 100644 --- a/project/src/backend/sdl/SDLStage.cpp +++ b/project/src/backend/sdl/SDLStage.cpp @@ -148,7 +148,6 @@ public: return swap ? pfARGBSwap : pfARGB; return swap ? pfXRGBSwap : pfXRGB; } - AlphaMode GetAlphaMode() const { return amStraight; } const uint8 *GetBase() const { return (const uint8 *)mSurf->pixels; } int GetStride() const { return mSurf->pitch; } diff --git a/project/src/backend/sdl2/SDL2Stage.cpp b/project/src/backend/sdl2/SDL2Stage.cpp index c10cd63f8..d474137d7 100644 --- a/project/src/backend/sdl2/SDL2Stage.cpp +++ b/project/src/backend/sdl2/SDL2Stage.cpp @@ -73,10 +73,6 @@ public: return swap ? pfARGBSwap : pfARGB; return swap ? pfXRGBSwap : pfXRGB; } - AlphaMode GetAlphaMode() const - { - return amStraight; - } const uint8 *GetBase() const { return (const uint8 *)mSurf->pixels; } int GetStride() const { return mSurf->pitch; } diff --git a/project/src/common/Display.cpp b/project/src/common/Display.cpp index 9b20b258e..fb1ae2753 100644 --- a/project/src/common/Display.cpp +++ b/project/src/common/Display.cpp @@ -1494,7 +1494,8 @@ public: mSurface = inStage->GetPrimarySurface(); mToFlip = inStage; mTarget = mSurface->BeginRender( Rect(mSurface->Width(),mSurface->Height()),false ); - mSurface->Clear(inRGB | 0xff000000 ); + + mSurface->Clear( (inRGB | 0xff000000) & inStage->getBackgroundMask() ); } int Width() const { return mSurface->Width(); } int Height() const { return mSurface->Height(); } diff --git a/project/src/common/ExternalInterface.cpp b/project/src/common/ExternalInterface.cpp index 791fb2c0b..87fbe1c2a 100644 --- a/project/src/common/ExternalInterface.cpp +++ b/project/src/common/ExternalInterface.cpp @@ -3588,25 +3588,6 @@ value lime_bitmap_data_multiply_alpha(value inSurface) DEFINE_PRIM(lime_bitmap_data_multiply_alpha,1); -value lime_bitmap_data_set_alpha_mode(value inHandle, value inAlphaMode) -{ - Surface *surface; - if (AbstractToObject(inHandle,surface)) - { - if ( val_int( inAlphaMode ) == 0 ) - surface->setAlphaMode( amUnknown ); - else if ( val_int( inAlphaMode ) == 1 ) - surface->setAlphaMode( amPremultiplied ); - else if ( val_int( inAlphaMode ) == 2 ) - surface->setAlphaMode( amStraight ); - else if ( val_int( inAlphaMode ) == 4 ) - surface->setAlphaMode( amIgnore ); - } - return alloc_null(); -} -DEFINE_PRIM(lime_bitmap_data_set_alpha_mode,2); - - value lime_render_surface_to_surface(value* arg, int nargs) { enum { aTarget, aSurface, aMatrix, aColourTransform, aBlendMode, aClipRect, aSmooth, aSIZE}; diff --git a/project/src/common/Graphics.cpp b/project/src/common/Graphics.cpp index c60c54756..c8c4ee498 100644 --- a/project/src/common/Graphics.cpp +++ b/project/src/common/Graphics.cpp @@ -2,6 +2,7 @@ #include "renderer/common/Surface.h" #include + namespace lime { @@ -638,18 +639,23 @@ bool Graphics::Render( const RenderTarget &inTarget, const RenderState &inState { if (!mHardwareData) mHardwareData = new HardwareData(); + else if (!mHardwareData->isScaleOk(inState)) + { + mHardwareData->clear(); + mBuiltHardware = 0; + } while(mBuiltHardwaremCalls.size()) + if (mHardwareData && !mHardwareData->mElements.empty()) { if (inState.mPhase==rpHitTest) - return inTarget.mHardware->Hits(inState,mHardwareData->mCalls); + return inTarget.mHardware->Hits(inState,*mHardwareData); else - inTarget.mHardware->Render(inState,mHardwareData->mCalls); + inTarget.mHardware->Render(inState,*mHardwareData); } } else diff --git a/project/src/common/Hardware.cpp b/project/src/common/Hardware.cpp index fd0b07dfb..1085c6f38 100644 --- a/project/src/common/Hardware.cpp +++ b/project/src/common/Hardware.cpp @@ -11,33 +11,75 @@ namespace lime { + +struct CurveEdge +{ + CurveEdge(const UserPoint &inP, float inT) : p(inP), t(inT) { } + inline CurveEdge(){} + + UserPoint p; + float t; +}; +typedef QuickVec Curves; + +struct Range +{ + inline Range() {} + inline Range(float inT0, const UserPoint &l0, const UserPoint &r0, + float inT1, const UserPoint &l1, const UserPoint &r1) : + t0(inT0), t1(inT1), + left0(l0), right0(r0), + left1(l1), right1(r1) { } + + float t0,t1; + UserPoint left0; + UserPoint right0; + UserPoint left1; + UserPoint right1; +}; + + + +typedef QuickVec Normals; + class HardwareBuilder { public: HardwareBuilder(const GraphicsJob &inJob,const GraphicsPath &inPath,HardwareData &ioData, - HardwareContext &inHardware) + HardwareContext &inHardware, const RenderState &inState) : data(ioData) { mTexture = 0; - bool tile_mode = false; - mElement.mColour = 0xffffffff; - mSolidMode = false; - mPerpLen = 0.5; + bool tessellate_lines = true; + bool tile_mode = false; + bool alphaAA = true; + + memset(&mElement,0,sizeof(mElement)); + mElement.mWidth = -1; + mElement.mColour = 0xffffffff; + mElement.mVertexOffset = ioData.mArray.size(); + mElement.mStride = 2*sizeof(float); + + mSolidMode = false; + mAlphaAA = false; + mPerpLen = 0.5; + mScale = data.scaleOf(inState); + if (mScale<=0.001) + mScale = 0.001; + mCurveThresh2 = 0.125/mScale/mScale; + mFatLineCullThresh = 5.0/mScale; if (inJob.mIsTileJob) { - mElement.mBitmapRepeat = true; - mElement.mBitmapSmooth = false; - mElement.mPrimType = ptTriangles; mElement.mScaleMode = ssmNormal; - mElement.mWidth = -1; GraphicsBitmapFill *bmp = inJob.mFill->AsBitmapFill(); - mSurface = bmp->bitmapData->IncRef(); - mTexture = mSurface->GetOrCreateTexture(inHardware); - mElement.mBitmapRepeat = false; - mElement.mBitmapSmooth = bmp->smooth; + mElement.mSurface = bmp->bitmapData->IncRef(); + + mTexture = mElement.mSurface->GetOrCreateTexture(inHardware); + if (bmp->smooth) + mElement.mFlags |= DRAW_BMP_SMOOTH; tile_mode = true; } else if (inJob.mFill) @@ -45,30 +87,45 @@ public: mSolidMode = true; mElement.mPrimType = inJob.mTriangles ? ptTriangles : ptTriangleFan; mElement.mScaleMode = ssmNormal; - mElement.mWidth = -1; if (!SetFill(inJob.mFill,inHardware)) return; } else if (tessellate_lines && inJob.mStroke->scaleMode==ssmNormal) { - // ptTriangleStrip? mElement.mPrimType = ptTriangles; GraphicsStroke *stroke = inJob.mStroke; + mElement.mWidth = stroke->thickness; if (!SetFill(stroke->fill,inHardware)) return; mPerpLen = stroke->thickness * 0.5; if (mPerpLen<=0.0) - mPerpLen = 0.5; - else if (mPerpLen<0.5) { mPerpLen = 0.5; + mElement.mWidth = 1.0; } mCaps = stroke->caps; mJoints = stroke->joints; - if (mJoints==sjMiter) - mMiterLimit = stroke->miterLimit*mPerpLen; + mMiterLimit = stroke->miterLimit*mPerpLen; + + if (mPerpLen<0.5/mScale) + { + int a = (mElement.mColour>>24)*mPerpLen*mScale/0.5; + mElement.mColour = (mElement.mColour & 0x00ffffff) | (a<<24); + mPerpLen = 0.5/mScale; + mElement.mWidth = 1.0/mScale; + } + + if (alphaAA) + { + mPerpLen += 0.5/mScale; + mElement.mWidth += 1.0/mScale; + mElement.mFlags |= DRAW_HAS_NORMAL; + mElement.mNormalOffset += mElement.mVertexOffset + mElement.mStride; + mElement.mStride += sizeof(float)*2.0; + mAlphaAA = true; + } } else { @@ -79,38 +136,59 @@ public: mElement.mWidth = stroke->thickness; SetFill(stroke->fill,inHardware); } - mElement.mFirst = 0; - mElement.mCount = 0; - - + + if (mElement.mSurface) + { + mElement.mFlags |= DRAW_HAS_TEX; + mElement.mTexOffset = mElement.mVertexOffset + mElement.mStride; + mElement.mStride += 2*sizeof(float); + } + if (inJob.mTriangles) { - bool has_colour = inJob.mTriangles->mColours.size()>0; - unsigned int flags = 0; - if (inJob.mTriangles->mType == vtVertexUVT) - flags |= HardwareArrays::PERSPECTIVE; - if (inJob.mTriangles->mBlendMode==bmAdd) - flags |= HardwareArrays::BM_ADD; - if (inJob.mTriangles->mBlendMode==bmMultiply) - flags |= HardwareArrays::BM_MULTIPLY; - if (inJob.mTriangles->mBlendMode==bmScreen) - flags |= HardwareArrays::BM_SCREEN; - if (mSurface && (mSurface->GetAlphaMode () == amPremultiplied)) - flags |= HardwareArrays::AM_PREMULTIPLIED; - mArrays = &ioData.GetArrays(mSurface,has_colour,flags); + if (inJob.mTriangles->mType == vtVertexUVT && mElement.mSurface) + { + // Add z,w to position coordinates... + mElement.mStride += 2*sizeof(float); + mElement.mTexOffset += 2*sizeof(float); + mElement.mFlags |= DRAW_HAS_PERSPECTIVE; + } + + if (inJob.mTriangles->mColours.size()) + { + mElement.mColourOffset = mElement.mVertexOffset + mElement.mStride; + mElement.mStride += sizeof(int); + mElement.mFlags |= DRAW_HAS_COLOUR; + mElement.mColour = 0xffffffff; + } + + mElement.mBlendMode =inJob.mTriangles->mBlendMode; + AddTriangles(inJob.mTriangles); if (inJob.mStroke && inJob.mStroke->fill) { + if (mElement.mSurface) + mElement.mSurface->DecRef(); + memset(&mElement,0,sizeof(mElement)); + mElement.mColour = 0xffffffff; + mElement.mVertexOffset = ioData.mArray.size(); + mElement.mStride = 2*sizeof(float); + mElement.mScaleMode = ssmNormal; + mElement.mWidth = inJob.mStroke->thickness; + mElement.mPrimType = ptLines; GraphicsStroke *stroke = inJob.mStroke; if (!SetFill(stroke->fill,inHardware)) return; - mArrays = &ioData.GetArrays(mSurface,false,mGradFlags); - mElement.mFirst = 0; - mElement.mCount = 0; - mElement.mScaleMode = ssmNormal; + if (mElement.mSurface) + { + mElement.mFlags |= DRAW_HAS_TEX; + mElement.mTexOffset = mElement.mVertexOffset + mElement.mStride; + mElement.mStride = 2*sizeof(float); + } + mElement.mWidth = stroke->thickness; AddTriangleLines(inJob.mTriangles); } @@ -118,36 +196,68 @@ public: else if (tile_mode) { bool has_colour = false; - BlendMode bm = bmNormal; - GetTileFlags(&inPath.commands[inJob.mCommand0], inJob.mCommandCount, has_colour, bm); - mArrays = &ioData.GetArrays(mSurface,has_colour,(bm == bmAdd) ? HardwareArrays::BM_ADD : (bm == bmMultiply) ? HardwareArrays::BM_MULTIPLY : (bm == bmScreen) ? HardwareArrays::BM_SCREEN : 0); - AddTiles(&inPath.commands[inJob.mCommand0], inJob.mCommandCount, &inPath.data[inJob.mData0]); + const uint8 *cmd = &inPath.commands[inJob.mCommand0]; + int cc = inJob.mCommandCount; + int tiles = 0; + + for(int i=0;iGetAlphaMode() == amPremultiplied)) ? mGradFlags | HardwareArrays::AM_PREMULTIPLIED : mGradFlags); AddLineTriangles(&inPath.commands[inJob.mCommand0], inJob.mCommandCount, &inPath.data[inJob.mData0]); } else { - mArrays = &ioData.GetArrays(mSurface,false,(mSurface && (mSurface->GetAlphaMode() == amPremultiplied)) ? mGradFlags | HardwareArrays::AM_PREMULTIPLIED : mGradFlags); AddObject(&inPath.commands[inJob.mCommand0], inJob.mCommandCount, &inPath.data[inJob.mData0]); } } - - + + void ReserveArrays(int inN) + { + mElement.mCount = inN; + data.mArray.resize( mElement.mVertexOffset + mElement.mStride*inN ); + } + + bool SetFill(IGraphicsFill *inFill,HardwareContext &inHardware) { - mSurface = 0; - mElement.mBitmapRepeat = true; - mElement.mBitmapSmooth = false; mGradFlags = 0; + if (mElement.mSurface) + { + mElement.mSurface->DecRef(); + mElement.mSurface = 0; + } GraphicsSolidFill *solid = inFill->AsSolidFill(); if (solid) { - //if (solid -> mRGB.a == 0) - //return false; mElement.mColour = solid->mRGB.ToInt(); } else @@ -157,37 +267,37 @@ public: { mGradReflect = grad->spreadMethod == smReflect; int w = mGradReflect ? 512 : 256; - mSurface = new SimpleSurface(w,1,pfARGB); - mSurface->IncRef(); - grad->FillArray( (ARGB *)mSurface->GetBase(), false); - - mElement.mBitmapRepeat = grad->spreadMethod!=smPad; - mElement.mBitmapSmooth = true; + mElement.mSurface = new SimpleSurface(w,1,pfARGB); + mElement.mSurface->IncRef(); + grad->FillArray( (ARGB *)mElement.mSurface->GetBase(), false); + if (grad->spreadMethod!=smPad) + mElement.mFlags |= DRAW_BMP_REPEAT; + mElement.mFlags |= DRAW_BMP_SMOOTH; + mTextureMapper = grad->matrix.Inverse(); if (!grad->isLinear) { - mGradFlags |= HardwareArrays::RADIAL; + mElement.mFlags |= DRAW_RADIAL; if (grad->focalPointRatio!=0) { - int r = fabs(grad->focalPointRatio)*256.0; - if (r>255) r = 255; - - mGradFlags |= (r << 8); - if (grad->focalPointRatio<0) - mGradFlags |= HardwareArrays::FOCAL_SIGN; + int r = grad->focalPointRatio*10000.0; + if (r<-10000) r = -10000; + if (r>10000) r = 10000; + mElement.mRadialPos = r; } } - //return true; } else { GraphicsBitmapFill *bmp = inFill->AsBitmapFill(); mTextureMapper = bmp->matrix.Inverse(); - mSurface = bmp->bitmapData->IncRef(); - mTexture = mSurface->GetOrCreateTexture(inHardware); - mElement.mBitmapRepeat = bmp->repeat; - mElement.mBitmapSmooth = bmp->smooth; + mElement.mSurface = bmp->bitmapData->IncRef(); + mTexture = mElement.mSurface->GetOrCreateTexture(inHardware); + if (bmp->repeat) + mElement.mFlags |= DRAW_BMP_REPEAT; + if (bmp->smooth) + mElement.mFlags |= DRAW_BMP_SMOOTH; } } //return false; @@ -196,22 +306,22 @@ public: ~HardwareBuilder() { - if (mSurface) - mSurface->DecRef(); + if (mElement.mSurface) + mElement.mSurface->DecRef(); } void CalcTexCoords() { - Vertices &vertices = mArrays->mVertices; - Vertices &tex = mArrays->mTexCoords; - int v0 = vertices.size(); - int t0 = tex.size(); - tex.resize(v0); - bool radial = mGradFlags & HardwareArrays::RADIAL; - for(int i=t0;ix,vertices->y); + Next(vertices); + if (mTexture) { p = mTexture->PixelToTex(p); @@ -238,102 +348,107 @@ public: p.x *= 0.5; } } - tex[i] = p; + *tex = p; + Next(tex); } } + + template + void Next(T *&ptr) + { + ptr = (T *)( (char *)ptr + mElement.mStride ); + } void AddTriangles(GraphicsTrianglePath *inPath) { - Vertices &vertices = mArrays->mVertices; - Colours &colours = mArrays->mColours; - Vertices &tex = mArrays->mTexCoords; - DrawElements &elements = mArrays->mElements; - bool persp = inPath->mType == vtVertexUVT; - mElement.mFirst = vertices.size() / (persp?2:1); + int n = inPath->mVertices.size(); + ReserveArrays(n); + + UserPoint *vertices = (UserPoint *)&data.mArray[ mElement.mVertexOffset ]; + int *colours = (mElement.mFlags & DRAW_HAS_COLOUR) ? (int *)&data.mArray[ mElement.mColourOffset ] : 0; + UserPoint *tex = (mElement.mFlags & DRAW_HAS_TEX) ? (UserPoint *)&data.mArray[ mElement.mTexOffset ] : 0; + bool persp = mElement.mFlags & DRAW_HAS_PERSPECTIVE; + int stride = mElement.mStride; + mElement.mPrimType = ptTriangles; const float *t = &inPath->mUVT[0]; - for(int v=0;vmVertices.size();v++) + for(int v=0;vmVertices[v]); - if(inPath->mColours.size()>0) - { - colours.push_back(inPath->mColours[v]);/*mwb*/ - } + *vertices = inPath->mVertices[v]; + Next(vertices); + } + + if(colours) + { + *colours = inPath->mColours[v]; + Next(colours); } if (inPath->mType != vtVertex) { - tex.push_back( mTexture->TexToPaddedTex( UserPoint(t[0],t[1]) ) ); + *tex = mTexture->TexToPaddedTex( UserPoint(t[0],t[1]) ); + Next(tex); + t+=2; if (persp) { float w= 1.0/ *t++; - vertices.push_back(inPath->mVertices[v]*w); - vertices.push_back( UserPoint(0,w) ); + vertices[0] = inPath->mVertices[v]*w; + vertices[1] = UserPoint(0,w); + Next(vertices); } } } - mElement.mCount = (vertices.size() - mElement.mFirst)/(persp ? 2:1); - elements.push_back(mElement); + mElement.mCount = n; + + PushElement(); } void AddTriangleLines(GraphicsTrianglePath *inPath) { - Vertices &vertices = mArrays->mVertices; - DrawElements &elements = mArrays->mElements; - mElement.mFirst = vertices.size(); mElement.mPrimType = ptLines; int tri_count = inPath->mVertices.size()/3; + ReserveArrays(tri_count*6); + + UserPoint *vertices = (UserPoint *)&data.mArray[mElement.mVertexOffset]; UserPoint *tri = &inPath->mVertices[0]; for(int v=0;vmVertices; - Vertices &tex = mArrays->mTexCoords; - Colours &colours = mArrays->mColours; - const UserPoint *point = (const UserPoint *)inData; - mElement.mFirst = vertices.size(); - - vertices.reserve(vertices.size() + (6 * inCount)); - tex.reserve(tex.size() + (6 * inCount)); - colours.reserve(colours.size() + (6 * inCount)); + UserPoint *point = (UserPoint *)inData; for(int i=0;iPixelToTex(tex_pos); - const UserPoint tp2 = mTexture->PixelToTex(UserPoint(tex_pos.x+size.x,tex_pos.y+size.y)); - tex.push_back( tp1 ); - tex.push_back( mTexture->PixelToTex(UserPoint(tex_pos.x+size.x,tex_pos.y)) ); - tex.push_back( tp2 ); - tex.push_back( tp1 ); - tex.push_back( tp2 ); - tex.push_back( mTexture->PixelToTex(UserPoint(tex_pos.x,tex_pos.y+size.y)) ); + pos = tex_pos; + *tex = ( mTexture->PixelToTex(pos) ); + Next(tex); + *tex = ( mTexture->PixelToTex(UserPoint(pos.x+size.x,pos.y)) ); + Next(tex); + *tex = ( mTexture->PixelToTex(UserPoint(pos.x+size.x,pos.y+size.y)) ); + Next(tex); + *tex = ( mTexture->PixelToTex(pos) ); + Next(tex); + *tex = ( mTexture->PixelToTex(UserPoint(pos.x+size.x,pos.y+size.y)) ); + Next(tex); + *tex = ( mTexture->PixelToTex(UserPoint(pos.x,pos.y+size.y)) ); + Next(tex); if (inCommands[i]&pcTile_Col_Bit) { - const UserPoint &rg = *point++; - const UserPoint &ba = *point++; + UserPoint rg = *point++; + UserPoint ba = *point++; #ifdef BLACKBERRY - const uint32 col = ((int)(rg.x*255)) | - (((int)(rg.y*255))<<8) | - (((int)(ba.x*255))<<16) | - (((int)(ba.y*255))<<24); + uint32 col = ((int)(rg.x*255)) | + (((int)(rg.y*255))<<8) | + (((int)(ba.x*255))<<16) | + (((int)(ba.y*255))<<24); #else - const uint32 col = ((rg.x<0 ? 0 : rg.x>1?255 : (int)(rg.x*255))) | - ((rg.y<0 ? 0 : rg.y>1?255 : (int)(rg.y*255))<<8) | - ((ba.x<0 ? 0 : ba.x>1?255 : (int)(ba.x*255))<<16) | - ((ba.y<0 ? 0 : ba.y>1?255 : (int)(ba.y*255))<<24); + uint32 col = ((rg.x<0 ? 0 : rg.x>1?255 : (int)(rg.x*255))) | + ((rg.y<0 ? 0 : rg.y>1?255 : (int)(rg.y*255))<<8) | + ((ba.x<0 ? 0 : ba.x>1?255 : (int)(ba.x*255))<<16) | + ((ba.y<0 ? 0 : ba.y>1?255 : (int)(ba.y*255))<<24); #endif - colours.push_back( col ); - colours.push_back( col ); - colours.push_back( col ); - colours.push_back( col ); - colours.push_back( col ); - colours.push_back( col ); + + *colours = ( col ); + Next(colours); + *colours = ( col ); + Next(colours); + *colours = ( col ); + Next(colours); + *colours = ( col ); + Next(colours); + *colours = ( col ); + Next(colours); + *colours = ( col ); + Next(colours); } } } } - mElement.mCount = vertices.size() - mElement.mFirst; + mElement.mCount = inTiles*6; if (mElement.mCount>0) - mArrays->mElements.push_back(mElement); + PushElement(); + } + + void PushElement() + { + if (mElement.mCount>0) + { + /* + if (data.mElements.size()>0) + { + DrawElement &e = data.mElements.last(); + if (e.mFlags==mElement.mFlags && + (e.mPrimType==ptLines || e.mPrimType==ptTriangles || e.mPrimType==ptPoints) && + e.mPrimType==mElement.mPrimType && + e.mBlendMode==mElement.mBlendMode && + e.mRadialPos==mElement.mRadialPos && + e.mSurface==mElement.mSurface && + e.mColour==mElement.mColour && + e.mWidth==mElement.mWidth ) + { + e.mCount += mElement.mCount; + return; + } + } + */ + data.mElements.push_back(mElement); + if (mElement.mSurface) + mElement.mSurface->IncRef(); + } + } + + void PushVertices(const Vertices &inV) + { + ReserveArrays(inV.size()); + + //printf("PushVertices %d\n", inV.size()); + + UserPoint *v = (UserPoint *)&data.mArray[mElement.mVertexOffset]; + for(int i=0;imVertices; - mElement.mFirst = vertices.size(); bool isConvex = inSubPolys.size()==1; if (mSolidMode) { @@ -473,16 +657,14 @@ public: } - mElement.mCount = inOutline.size(); - vertices.resize(mElement.mFirst + mElement.mCount); - for(int i=0;imElements.push_back(mElement); + mElement.mVertexOffset = data.mArray.size(); + if (mElement.mSurface) + mElement.mTexOffset = mElement.mVertexOffset + 2*sizeof(float); + + PushVertices(inOutline); if (!isConvex) - mArrays->mElements.last().mPrimType = ptTriangles; + data.mElements.last().mPrimType = ptTriangles; } @@ -610,207 +792,285 @@ public: UserPoint curve; }; - void AddArc(Vertices &vertices,UserPoint inP, double angle, UserPoint inVx, UserPoint inVy, UserPoint p0, UserPoint p1) + void AddArc(Curves &outCurve, UserPoint inP, double angle, UserPoint inVx, UserPoint inVy, float t) { - int steps = 1 + angle*8; + int steps = 1 + mPerpLen*angle*3; + if (steps>60) + steps = 60; double d_theta = angle / (steps+1); double theta = d_theta; - for(int i=0;imMiterLimit) { UserPoint corner0 = p0+dir1*mMiterLimit; UserPoint corner1 = p1-dir2*mMiterLimit; - vertices.push_back(inP); - vertices.push_back(p0); - vertices.push_back(corner0); - - vertices.push_back(inP); - vertices.push_back(corner0); - vertices.push_back(corner1); - - vertices.push_back(inP); - vertices.push_back(corner1); - vertices.push_back(p1); + outCurves.push_back( CurveEdge(corner0, t+0.33) ); + outCurves.push_back( CurveEdge(corner1, t+0.66) ); } else { - UserPoint corner = p0+dir1*inAlpha; - vertices.push_back(inP); - vertices.push_back(p0); - vertices.push_back(corner); - - vertices.push_back(inP); - vertices.push_back(corner); - vertices.push_back(p1); + UserPoint corner0 = p0+dir1*inAlpha; + UserPoint corner1 = p1-dir2*inAlpha; + UserPoint diff = corner1-corner0; + outCurves.push_back( CurveEdge(corner1, t+0.501) ); } } - - void AddCurveSegment(Vertices &vertices,UserPoint inP0,UserPoint inP1,UserPoint inP2, UserPoint perp0, UserPoint perp1, - UserPoint p0_left, UserPoint p0_right, UserPoint p1_left, UserPoint p1_right) + + + void removeLoops(QuickVec &curve,int startPoint,float turningPoint) { - double len = (inP0 - inP1).Norm() + (inP2 - inP1).Norm(); - - int steps = (int)len*0.1; - - if (len < 50 && steps < 10) steps = 50; - else if (steps < 1) steps = 1; - else if (steps > 100) steps = 100; - - double step = 1.0 / (steps); - double t = 0; - - UserPoint v0 = p0_right - p0_left; - UserPoint v1 = p1_right - p1_left; - - UserPoint last_p_left = inP0 - perp0; - UserPoint last_p_right = inP0 + perp0; - - // Clip against end ... - if ( v0.Cross(last_p_left-p0_left)>0 ) - last_p_left = p0_left; - if ( v0.Cross(last_p_right-p0_left)>0 ) - last_p_right = p0_right; - // TODO - against other end? - for (int s=1; s <= steps; s++) + for(int i=startPoint;iturningPoint; + for(int j=i+2;j0) - p_left = p0_left; - if ( v0.Cross(p_right-p0_left)>0) - p_right = p0_right; - } + const UserPoint &l0 = curve[j].p; + const UserPoint &l1 = curve[j+1].p; + if ( (l0.xmaxX && l1.x>maxX) || + (l0.ymaxY && l1.y>maxY) ) + continue; - if (v1.Cross(dir) < 0 ) // if pointing in same direction (left-handed) - { - if ( v1.Cross(p_left-p1_left)<0) - p_left = p1_left; - if ( v1.Cross(p_right-p1_left)<0) - p_right = p1_right; - } + // Only consider intersection with self or joint for second half of curve + if (turningPoint>0 && curve[j].t>turningPoint && cti<(int)curve[j].t-1) + break; - if (p_left==last_p_left) - { - if (p_right!=last_p_right) + UserPoint dl = l1-l0; + // Solve p0.x + a dp.x = l0.x + b dl.x + // p0.y + a dp.y = l0.y + b dl.y + + // Solve p0.x*dp.y + a dp.x*dp.y = l0.x*dp.y + b dl.x*dp.y + // p0.y*dp.x + a dp.y*dp.x = l0.y*dp.x + b dl.y*dp.x + // p0 x dp - l0 x dp = b dl x dp + // (p0-l0) x dp = b dl x dp + double denom = dl.Cross(dp); + if (denom!=0.0) { - vertices.push_back(p_left); - vertices.push_back(last_p_right); - vertices.push_back(p_right); + double b = (p0-l0).Cross(dp)/denom; + if (b>=0 && b<=1.0) + { + double a = (fabs(dp.x) > fabs(dp.y)) ? (l0.x + b*dl.x - p0.x)/dp.x : + (l0.y + b*dl.y - p0.y)/dp.y; + if (a>=0 && a<=1) + { + if (a>0 && a<1 && b>0 && b<1) + { + UserPoint p = p0 + dp*a; + // Remove the loop + // c[i] + // p <- new point between c[i] and c[i+1] + // c[i+1] + // c[i+2] + // ... + // c[j] + // p <- new point between c[j] and c[j+1] + // c[j+1] + { + // replace c[i+1] with p, and erase upto and including c[j] + p1 = p; + curve.EraseAt(i+2,j+1); + break; + } + } + } + } } } - else if (p_right==last_p_right) + } + } + + + void AddCurveSegment(Curves &leftCurve, Curves &rightCurve, + UserPoint perp0, UserPoint perp1, + UserPoint inP0,UserPoint inP1,UserPoint inP2, + UserPoint p0_left, UserPoint p0_right,UserPoint p1_left, UserPoint p1_right, float t0) + { + + QuickVec stack; + Range r0(0,inP0-perp0, inP0+perp0, 1,inP2-perp1, inP2+perp1); + stack.push_back(r0); + + while(stack.size()) + { + Range r = stack.qpop(); + if (r.t1-r.t0 > 0.001 ) { - if (p_left!=last_p_left) + // Calc midpoint... + double t = (r.t0+r.t1)*0.5; + double t_ = 1.0 - t; + UserPoint mid_p = inP0 * (t_ * t_) + inP1 * (2.0 * t * t_) + inP2 * (t * t); + UserPoint dir = (inP0 * -t_ + inP1 * (1.0 - 2.0 * t) + inP2 * t); + UserPoint mid_l = mid_p - dir.Perp(mPerpLen); + UserPoint mid_r = mid_p + dir.Perp(mPerpLen); + + UserPoint average_l = (r.left0+r.left1)*0.5; + UserPoint average_r = (r.right0+r.right1)*0.5; + if ( mid_l.Dist2(average_l)>mCurveThresh2 || mid_r.Dist2(average_r)>mCurveThresh2) { - vertices.push_back(last_p_left); - vertices.push_back(p_right); - vertices.push_back(p_left); + // Reverse order, LIFO + stack.push_back( Range(t,mid_l,mid_r, r.t1,r.left1,r.right1) ); + r.t1 = t; + r.left1 = mid_l; + r.right1 = mid_r; + stack.push_back(r); + continue; } + // Too much curvature? + // dir = pert @ mid_t + /* + t+=0.001; + t_ = 1.0 - t; + UserPoint p_plus = inP0 * (t_ * t_) + inP1 * (2.0 * t * t_) + inP2 * (t * t); + UserPoint perp_plus = (inP0 * -t_ + inP1 * (1.0 - 2.0 * t) + inP2 * t).Perp(mPerpLen); + + if (r.t0==0.0 || (mid_p-p_plus).Dot(mid_l-(p_plus-perp_plus)) > 0) + leftCurve.push_back( CurveEdge(r.left0,r.t0+t0) ); + + if ( (mid_p-p_plus).Dot(mid_r-(p_plus+perp_plus)) > 0) + rightCurve.push_back( CurveEdge(r.right0,r.t0+t0) ); + + continue; + */ + } + leftCurve.push_back( CurveEdge(r.left0,r.t0+t0) ); + rightCurve.push_back( CurveEdge(r.right0,r.t0+t0) ); + } + leftCurve.push_back( CurveEdge(inP2-perp1,0.9999+t0) ); + rightCurve.push_back( CurveEdge(inP2+perp1,0.9999+t0) ); + } + + void EndCap(Curves &left, Curves &right, UserPoint p0, UserPoint perp, double t) + { + bool first = t==0; + + UserPoint back(-perp.y, perp.x); + if (!first) + { + back.x*=-1; + back.y*=-1; + } + + if (mCaps==scSquare) + { + if (first) + { + left.push_back(CurveEdge(p0+back,t)); + right.push_back(CurveEdge(p0+back,t)); + + left.push_back(CurveEdge(p0+back-perp,t+0.5)); + right.push_back(CurveEdge(p0+back+perp,t+0.5)); } else { - vertices.push_back(last_p_left); - vertices.push_back(last_p_right); - vertices.push_back(p_left); + left.push_back(CurveEdge(p0-perp,t)); + right.push_back(CurveEdge(p0+perp,t)); - vertices.push_back(p_left); - vertices.push_back(last_p_right); - vertices.push_back(p_right); + left.push_back(CurveEdge(p0+back-perp,t+0.5)); + right.push_back(CurveEdge(p0+back+perp,t+0.5)); } - - last_p_left = p_left; - last_p_right = p_right; - } - } - - void EndCap(Vertices &vertices,UserPoint p0, UserPoint perp) - { - UserPoint back(-perp.y, perp.x); - if (mCaps==scSquare) - { - vertices.push_back(p0+perp); - vertices.push_back(p0+perp + back); - vertices.push_back(p0-perp); - - vertices.push_back(p0+perp + back); - vertices.push_back(p0-perp + back); - vertices.push_back(p0-perp); } else { int n = std::max(2,(int)(mPerpLen * 4)); - double dtheta = M_PI / n; - double theta = 0.0; - UserPoint prev(perp); + double dtheta = M_PI*0.5 / n; + for(int i=1;ip + + */ + + float dist = fabs( (p-base).Dot( (p-prev).Perp(1.0) ) ); + if (!inAllowSmaller && dist &inPath, bool inLoop) { - Vertices &vertices = mArrays->mVertices; - mElement.mFirst = vertices.size(); + if (inPath.size()<2) + return; + + Curves leftCurve; + Curves rightCurve; + + float t = 0.0; + int prevSegLeft = 0; + int prevSegRight = 0; // Endcap 0 ... - if (!inLoop && (mCaps==scSquare || mCaps==scRound)) + if (!inLoop) { - UserPoint p0 = inPath[0].p; - EndCap(vertices, p0, inPath[1].getDir0(p0).Perp(mPerpLen)); + if (mCaps==scSquare || mCaps==scRound) + { + UserPoint p0 = inPath[0].p; + EndCap(leftCurve, rightCurve, p0, inPath[1].getDir0(p0).Perp(mPerpLen),t); + } } + t+=1.0; + + UserPoint p; + UserPoint dir1; - double prev_alpha = 0; for(int i=1;i next_perp-perp1 = alpha*(dir1+next_dir) - -> alpha = prep1-next_perp in either x or y direction... - --------------- - dir1+next_dir - - Make the split such that DpY and down belongs to this segment - first add this DpY triangle, then - the remainder of the segment happens below the D-Y line. - - On one side (right hand, drawn here) the segments will overlap - on the other side, there - will be a join. Which side this will be depends on the sign of alpha. When reversed, the - roles of Y and Z will change. - - BpY is for this upper segment - but there is an equivalent B'p0Y' for this segment. - First we add B'p-Y' triangle, and work from B'Y' line - */ UserPoint perp0(-dir0.y*mPerpLen, dir0.x*mPerpLen); UserPoint perp1(-dir1.y*mPerpLen, dir1.x*mPerpLen); UserPoint next_perp(-next_dir.y*mPerpLen, next_dir.x*mPerpLen); - double denom_x = dir1.x+next_dir.x; - double denom_y = dir1.y+next_dir.y; - double alpha=0; - - // Choose the better-conditioned axis - if (fabs(denom_x)>fabs(denom_y)) - alpha = denom_x==0 ? 0 : (perp1.x-next_perp.x)/denom_x; - else - alpha = denom_y==0 ? 0 : (perp1.y-next_perp.y)/denom_y; UserPoint p1_left = p-perp1; UserPoint p1_right = p+perp1; - // This could start getting dodgy when the line doubles-back - double max_alpha = std::max( (p0-p).Norm()*0.5, mPerpLen ); - if (fabs(alpha)>max_alpha) - { - // draw overlapped - } - else if (alpha>0) - { - p1_right -= dir1 * alpha; - vertices.push_back(p1_left); - vertices.push_back(p); - vertices.push_back(p1_right); - } - else if (alpha<0) - { - p1_left += dir1 * alpha; - vertices.push_back(p1_left); - vertices.push_back(p); - vertices.push_back(p1_right); - } - UserPoint p0_left = p0-perp0; UserPoint p0_right = p0+perp0; - if (i==1 && inLoop) - { - UserPoint prev_dir = inPath[inPath.size()-1].getDir1(inPath[inPath.size()-2].p).Normalized(); - UserPoint prev_perp(-prev_dir.y*mPerpLen, prev_dir.x*mPerpLen); - double denom_x = prev_dir.x+dir0.x; - double denom_y = prev_dir.y+dir0.y; - - // Choose the better-conditioned axis - if (fabs(denom_x)>fabs(denom_y)) - prev_alpha = denom_x==0 ? 0 : (prev_perp.x-perp0.x)/denom_x; - else - prev_alpha = denom_y==0 ? 0 : (prev_perp.y-perp0.y)/denom_y; - } - - if (fabs(prev_alpha)>max_alpha) - { - // do nothing - } - else if (prev_alpha>0) - { - p0_right += dir0 * std::min(prev_alpha,max_alpha); - vertices.push_back(p0_left); - vertices.push_back(p0); - vertices.push_back(p0_right); - } - else if (prev_alpha<0) - { - p0_left -= dir0 * std::max(prev_alpha,-max_alpha); - vertices.push_back(p0_left); - vertices.push_back(p0); - vertices.push_back(p0_right); - } - - if (alpha) - switch(mPerpLen<1 ? sjBevel : mJoints) - { - case sjRound: - { - double angle = acos(dir1.Dot(next_dir)); - if (angle<0) angle += M_PI; - if (alpha>0) // left - AddArc(vertices, p, angle, -perp1, dir1*mPerpLen, p1_left, p-next_perp ); - else // right - AddArc(vertices, p, angle, perp1, dir1*mPerpLen, p1_right, p+next_perp ); - } - break; - - case sjMiter: - if (alpha>0) // left - AddMiter(vertices, p, p-perp1, p-next_perp, alpha, dir1, next_dir); - else // Right - AddMiter(vertices, p, p+perp1, p+next_perp, -alpha, dir1, next_dir); - break; - - case sjBevel: - if (alpha>0) // left - { - vertices.push_back(p1_left); - vertices.push_back(p); - vertices.push_back(p-next_perp); - } - else - { - vertices.push_back(p1_right); - vertices.push_back(p); - vertices.push_back(p+next_perp); - } - break; - } + int segStartLeft = leftCurve.size(); + int segStartRight = rightCurve.size(); if (seg.isCurve()) { - AddCurveSegment(vertices,p0,seg.curve,seg.p, perp0, perp1, p0_left, p0_right, p1_left, p1_right); + AddCurveSegment(leftCurve,rightCurve,perp0, perp1,p0,seg.curve,seg.p, p0_left, p0_right, p1_left, p1_right,t); + t+=1.0; } else { - vertices.push_back(p0_left); - vertices.push_back(p0_right); - vertices.push_back(p1_right); + leftCurve.push_back( CurveEdge(p0_left,t) ); + leftCurve.push_back( CurveEdge(p1_left,t+0.99) ); - vertices.push_back(p0_left); - vertices.push_back(p1_right); - vertices.push_back(p1_left); + rightCurve.push_back( CurveEdge(p0_right,t) ); + rightCurve.push_back( CurveEdge(p1_right,t+0.99) ); + + t+=1.0; } - // Endcap end ... - if (!inLoop && (i+1==inPath.size()) && (mCaps==scSquare || mCaps==scRound)) - EndCap(vertices, p, dir1.Perp(-mPerpLen)); + float segJoinLeft = leftCurve.last().t; + float segJoinRight = rightCurve.last().t; - prev_alpha = alpha; + bool reversed = next_dir.Dot(dir1)<0; + bool fullReverse = reversed && next_dir.Dot(dir1)<-0.99; + if (fullReverse) + { + leftCurve.push_back( CurveEdge(p1_right,t) ); + rightCurve.push_back( CurveEdge(p1_left,t) ); + segStartLeft = prevSegLeft = leftCurve.size(); + segStartRight = prevSegRight = rightCurve.size(); + } + else if (mPerpLen>1 && (mJoints==sjRound || mJoints==sjMiter) && (reversed || fabs(next_dir.Cross(dir1))>0.25 ) ) + { + /* + + --- + --- + --- + - B- next segment + Z \ ... + | \ ... + D_____\ ...____ + | p C ---. + | .\ | --- + | . \ -Y- + | . A-- | + | . | + | . | p = end segment + | . | + | . | + | . | + + A = p + next_perp + B = p - next_perp + + C = p + perp1 + D = p - perp1 + + Y = A + alpha*next_dir + = C - alpha*dir1 + + = p + next_perp + alpha*next_dir + = p + perp1 - alpha*dir1 + + -> next_perp-perp1 = alpha*(dir1+next_dir) + -> alpha = prep1-next_perp in either x or y direction... + --------------- + dir1+next_dir + + On the overlap side, we will draw a bevel, and let the removeLoops code fix it. + On the non-overlay side, we will draw a joint + */ + + + + double denom_x = dir1.x+next_dir.x; + double denom_y = dir1.y+next_dir.y; + double alpha=0; + + // Choose the better-conditioned axis + if (fabs(denom_x)>fabs(denom_y)) + alpha = denom_x==0 ? 0 : (perp1.x-next_perp.x)/denom_x; + else + alpha = denom_y==0 ? 0 : (perp1.y-next_perp.y)/denom_y; + + if ( fabs(alpha)>0.01 ) + { + if (mJoints==sjRound) + { + double angle = acos(dir1.Dot(next_dir)); + if (angle<0) angle += M_PI; + if (alpha>0) // left + AddArc(leftCurve, p, angle, -perp1, dir1*mPerpLen, t ); + else // right + AddArc(rightCurve, p, angle, perp1, dir1*mPerpLen, t ); + } + else + { + if (alpha>0) // left + { + AddMiter(leftCurve, p, p1_left, p-next_perp, alpha, dir1, next_dir,t); + } + else // Right + { + AddMiter(rightCurve, p, p1_right, p+next_perp, -alpha, dir1, next_dir,t); + } + } + } + } + t+=1.0; + + float turnLeft = seg.isCurve() ? segJoinLeft - 0.66 : 0; + float turnRight = seg.isCurve() ? segJoinRight - 0.66 : 0; + removeLoops(leftCurve,prevSegLeft,turnLeft); + removeLoops(rightCurve,prevSegRight,turnRight); + + prevSegLeft = segStartLeft; + prevSegRight = segStartRight; } + // Endcap end ... + if (!inLoop && (mCaps==scSquare || mCaps==scRound)) + { + EndCap(leftCurve, rightCurve, p, dir1.Perp(mPerpLen),t); + } - mElement.mCount = vertices.size()-mElement.mFirst; - if (mSurface) + removeLoops(leftCurve,prevSegLeft,0); + removeLoops(rightCurve,prevSegRight,0); + + + if (leftCurve.size()<2 || rightCurve.size()<2) + return; + + bool useTriStrip = true; + bool keepTriSense = true; + + data.mArray.reserve( mElement.mVertexOffset + (leftCurve.size() + rightCurve.size()) * mElement.mStride * (useTriStrip?2:3) ); + + UserPoint *v = (UserPoint *)&data.mArray[mElement.mVertexOffset]; + UserPoint *normal = (mElement.mFlags & DRAW_HAS_NORMAL) ? (UserPoint *)&data.mArray[mElement.mNormalOffset] : 0; + + UserPoint pLeft = leftCurve[0].p; + UserPoint pRight = rightCurve[0].p; + + UserPoint leftNormal(mElement.mWidth*0.5, -mPerpLen); + UserPoint rightNormal(mElement.mWidth*0.5, mPerpLen); + + + if (useTriStrip) + { + *v = pRight; Next(v); + if (normal) + { *normal = rightNormal; Next(normal); } + + *v = pLeft; Next(v); + if (normal) + { *normal = leftNormal; Next(normal); } + } + + int added = useTriStrip ? 2 : 0; + int left = 1; + int right = 1; + + + enum { PREV_LEFT, PREV_RIGHT }; + int prevEdge = PREV_LEFT; + + + while(left=leftCurve.size() || (right=0) + { + if (!useTriStrip) + { + *v = pRight; Next(v); + if (normal) + { *normal = rightNormal; Next(normal); } + + *v = pLeft; Next(v); + if (normal) + { *normal = leftNormal; Next(normal); } + added+=2; + } + else if (keepTriSense && prevEdge!=PREV_LEFT) + { + *v = pLeft; Next(v); + if (normal) + { *normal = leftNormal; Next(normal); } + added++; + } + added++; + if (normal) + { + *normal = rightNormal = CalcNormalInfo(pLeft, pRight, test, 1.0, testT<1 ||testT>=t); + Next(normal); + } + *v = pRight = test; + Next(v); + prevEdge = PREV_RIGHT; + } + } + else + { + float testT = rightCurve[left].t; + UserPoint test = leftCurve[left++].p; + if ( mPerpLen=0) + { + if (!useTriStrip) + { + *v = pRight; Next(v); + if (normal) + { *normal = rightNormal; Next(normal); } + + *v = pLeft; Next(v); + if (normal) + { *normal = leftNormal; Next(normal); } + added+=2; + } + else if (keepTriSense && prevEdge!=PREV_RIGHT) + { + *v = pRight; Next(v); + if (normal) + { *normal = rightNormal; Next(normal); } + added++; + } + + added++; + if (normal) + { + *normal = leftNormal = CalcNormalInfo(pRight, pLeft, test, -1.0, testT<1 || testT>=t); + Next(normal); + } + *v = pLeft = test; + Next(v); + prevEdge = PREV_LEFT; + } + } + } + + // Build triangle strip.... + mElement.mPrimType = useTriStrip ? ptTriangleStrip : ptTriangles; + mElement.mCount = added; + data.mArray.resize( mElement.mVertexOffset + mElement.mCount*mElement.mStride ); + + if (mElement.mSurface) CalcTexCoords(); - mArrays->mElements.push_back(mElement); - } + PushElement(); + } + + void AddLineTriangles(const uint8* inCommands, int inCount, const float *inData) { UserPoint *point = (UserPoint *)inData; @@ -1098,21 +1441,34 @@ public: } } - if (strip.size()>0) + if (strip.size()>1) + { + float s = mScale * 0.707; + if (data.mMinScale==0 || s>data.mMinScale) + data.mMinScale = s; + + s = mScale * 1.41; + if (data.mMaxScale==0 || sAsSolidFill() : 0; if (fill) @@ -1140,90 +1497,124 @@ void CreatePointJob(const GraphicsJob &inJob,const GraphicsPath &inPath,Hardware } elem.mPrimType = ptPoints; + elem.mVertexOffset = ioData.mArray.size(); + elem.mStride = sizeof(float)*2; + if (!fill) + { + elem.mColourOffset = elem.mVertexOffset + elem.mStride; + elem.mStride += sizeof(int); + elem.mFlags |= DRAW_HAS_COLOUR; + elem.mColour = 0xffffffff; + } elem.mCount = inJob.mDataCount / (fill ? 2 : 3); + ioData.mArray.resize( elem.mVertexOffset + elem.mStride*elem.mCount ); - HardwareArrays *arrays = &ioData.GetArrays(0,fill==0, /* TODO: bm add ? */ 0); - Vertices &vertices = arrays->mVertices; - elem.mFirst = vertices.size(); - vertices.resize( elem.mFirst + elem.mCount ); - memcpy( &vertices[elem.mFirst], &inPath.data[ inJob.mData0 ], elem.mCount*sizeof(UserPoint) ); + UserPoint *srcV = (UserPoint *)&inPath.data[ inJob.mData0 ]; + UserPoint *v = (UserPoint *)&ioData.mArray[ elem.mVertexOffset ]; + + for(int i=0;imColours; - colours.resize( elem.mFirst + elem.mCount ); const int * src = (const int *)(&inPath.data[ inJob.mData0 + elem.mCount*2]); - int * dest = &colours[elem.mFirst]; - int n = elem.mCount; - for(int i=0;i>16)&0xff) | ((s<<16) & 0xff0000); + *dest = (s & 0xff00ff00) | ((s>>16)&0xff) | ((s<<16) & 0xff0000); + dest = (int *)( (char *)dest + elem.mStride ); } } - arrays->mElements.push_back(elem); + ioData.mElements.push_back(elem); } void BuildHardwareJob(const GraphicsJob &inJob,const GraphicsPath &inPath,HardwareData &ioData, - HardwareContext &inHardware) + HardwareContext &inHardware, const RenderState &inState) { + ioData.releaseVbo(); + if (inJob.mIsPointJob) CreatePointJob(inJob,inPath,ioData,inHardware); else { - HardwareBuilder builder(inJob,inPath,ioData,inHardware); + HardwareBuilder builder(inJob,inPath,ioData,inHardware, inState); } } -// --- HardwareArrays --------------------------------------------------------------------- - -HardwareArrays::HardwareArrays(Surface *inSurface,unsigned int inFlags) -{ - mFlags = inFlags; - mSurface = inSurface; - if (inSurface) - inSurface->IncRef(); -} - -HardwareArrays::~HardwareArrays() -{ - if (mSurface) - mSurface->DecRef(); -} - -bool HardwareArrays::ColourMatch(bool inWantColour) -{ - if (mVertices.empty()) - return true; - return mColours.empty() != inWantColour; -} - - - // --- HardwareData --------------------------------------------------------------------- + +HardwareData::HardwareData() +{ + mRendersWithoutVbo = 0; + mVertexBo = 0; + mContextId = 0; + mVboOwner = 0; + mMinScale = mMaxScale = 0.0; +} + +void HardwareData::releaseVbo() +{ + if (mVboOwner) + { + if (mVertexBo && mContextId==gTextureContextVersion) + mVboOwner->DestroyVbo(mVertexBo); + mVboOwner->DecRef(); + mVboOwner=0; + } + mContextId = 0; + mVertexBo = 0; + mRendersWithoutVbo = 0; +} + +float HardwareData::scaleOf(const RenderState &inState) const +{ + const Matrix &m = *inState.mTransform.mMatrix; + return sqrt( 0.5*( m.m00*m.m00 + m.m01*m.m01 + m.m10*m.m10 + m.m11*m.m11 ) ); +} + +bool HardwareData::isScaleOk(const RenderState &inState) const +{ + if (mMinScale==0 && mMaxScale==0) + return true; + + float scale = scaleOf(inState); + if (mMinScale>0 && scale0 && scale>mMaxScale) + { + //printf("%f>%f\n", scale, mMaxScale); + return false; + } + return true; +} + + +void HardwareData::clear() +{ + releaseVbo(); + mArray.resize(0); + mElements.resize(0); + mMinScale = mMaxScale = 0.0; +} + HardwareData::~HardwareData() { - mCalls.DeleteAll(); + releaseVbo(); + for(int i=0;iDecRef(); } -HardwareArrays &HardwareData::GetArrays(Surface *inSurface,bool inWithColour,unsigned int inFlags) -{ - if (mCalls.empty() || mCalls.last()->mSurface != inSurface || - !mCalls.last()->ColourMatch(inWithColour) || - mCalls.last()->mFlags != inFlags ) - { - HardwareArrays *arrays = new HardwareArrays(inSurface,inFlags); - mCalls.push_back(arrays); - } - - return *mCalls.last(); -} - - - // --- Texture ----------------------------- void Texture::Dirty(const Rect &inRect) { @@ -1243,7 +1634,48 @@ double sLineScaleH = -1; double sLineScaleNormal = -1; -bool HardwareContext::Hits(const RenderState &inState, const HardwareCalls &inCalls ) +inline bool HitTri(const UserPoint &base, const UserPoint &_v0, const UserPoint &_v1, const UserPoint &pos) +{ + bool bgx = pos.x>base.x; + if ( bgx!=(pos.x>_v0.x) || bgx!=(pos.x>_v1.x) ) + { + bool bgy = pos.y>base.y; + if ( bgy!=(pos.y>_v0.y) || bgy!=(pos.y>_v1.y) ) + { + UserPoint v0 = _v0 - base; + UserPoint v1 = _v1 - base; + UserPoint v2 = pos - base; + double dot00 = v0.Dot(v0); + double dot01 = v0.Dot(v1); + double dot02 = v0.Dot(v2); + double dot11 = v1.Dot(v1); + double dot12 = v1.Dot(v2); + + // Compute barycentric coordinates + double denom = (dot00 * dot11 - dot01 * dot01); + if (denom!=0) + { + denom = 1 / denom; + double u = (dot11 * dot02 - dot01 * dot12) * denom; + if (u>=0) + { + double v = (dot00 * dot12 - dot01 * dot02) * denom; + + // Check if point is in triangle + if ( (v >= 0) && (u + v < 1) ) + return true; + } + } + } + } + + return false; +} + + + + +bool HardwareContext::Hits(const RenderState &inState, const HardwareData &inData ) { if (inState.mClipRect.w!=1 || inState.mClipRect.h!=1) return false; @@ -1260,164 +1692,137 @@ bool HardwareContext::Hits(const RenderState &inState, const HardwareCalls &inCa } - for(int c=0;cx1) prev |= 0x02; - if (p0.yy1) prev |= 0x08; - if (prev==0 && pos.Dist2(p0)<=w2) + int prev = 0; + if (p0.xx1) prev |= 0x02; + if (p0.yy1) prev |= 0x08; + if (prev==0 && pos.Dist2(p0)<=w2) + return true; + for(int i=1;ix1) flags |= 0x02; + if (p.yy1) flags |= 0x08; + if (flags==0 && pos.Dist2(p)<=w2) return true; - for(int i=1;ix1) flags |= 0x02; - if (p.yy1) flags |= 0x08; - if (flags==0 && pos.Dist2(p)<=w2) - return true; - if ( !(flags & prev) ) + // Line *may* pass though the point... + UserPoint vec = p-p0; + double len = sqrt(vec.x*vec.x + vec.y*vec.y); + if (len>0) { - // Line *may* pass though the point... - UserPoint vec = p-p0; - double len = sqrt(vec.x*vec.x + vec.y*vec.y); - if (len>0) + double a = vec.Dot(pos-p0)/len; + if (a>0 && a<1) { - double a = vec.Dot(pos-p0)/len; - if (a>0 && a<1) - { - if ( (p0 + vec*a).Dist2(pos) < w2 ) - return true; - } + if ( (p0 + vec*a).Dist2(pos) < w2 ) + return true; } } - prev = flags; - p0 = p; } + prev = flags; + p0 = p; } - else if (draw.mPrimType == ptTriangleFan) + } + else if (draw.mPrimType == ptTriangleFan) + { + if (draw.mCount<3) + continue; + UserPoint p0 = V(0); + int count_left = 0; + for(int i=1;i<=draw.mCount;i++) { - if (draw.mCount<3) - continue; - UserPoint *v = &vert[ draw.mFirst ]; - UserPoint p0 = *v; - int count_left = 0; - for(int i=1;i<=draw.mCount;i++) + UserPoint p = V(i%draw.mCount); + if ( (p.ybase.x; - if ( bgx!=(pos.x>v[0].x) || bgx!=(pos.x>v[1].x) ) - { - bool bgy = pos.y>base.y; - if ( bgy!=(pos.y>v[0].y) || bgy!=(pos.y>v[1].y) ) - { - UserPoint v0 = v[0] - base; - UserPoint v1 = v[1] - base; - UserPoint v2 = pos - base; - double dot00 = v0.Dot(v0); - double dot01 = v0.Dot(v1); - double dot02 = v0.Dot(v2); - double dot11 = v1.Dot(v1); - double dot12 = v1.Dot(v2); - - // Compute barycentric coordinates - double denom = (dot00 * dot11 - dot01 * dot01); - if (denom!=0) - { - denom = 1 / denom; - double u = (dot11 * dot02 - dot01 * dot12) * denom; - if (u>=0) - { - double v = (dot00 * dot12 - dot01 * dot02) * denom; - - // Check if point is in triangle - if ( (v >= 0) && (u + v < 1) ) - return true; - } - } - } - } - v+=2; - } + if (HitTri(V(i-2), V(i-2),V(i), pos )) + return true; } } } diff --git a/project/src/common/Tessellate.cpp b/project/src/common/Tessellate.cpp index c18bdcf24..37bb71e6f 100644 --- a/project/src/common/Tessellate.cpp +++ b/project/src/common/Tessellate.cpp @@ -1,5 +1,6 @@ #include #include +#include namespace lime { diff --git a/project/src/common/TextField.cpp b/project/src/common/TextField.cpp index 433a32aad..f356d49b1 100644 --- a/project/src/common/TextField.cpp +++ b/project/src/common/TextField.cpp @@ -1430,6 +1430,8 @@ void TextField::Render( const RenderTarget &inTarget, const RenderState &inState int line = 0; int last_line = mLines.size()-1; + Surface *hardwareSurface = 0; + uint32 hardwareTint = 0; for(int g=0;g=mSelectMin && cidBeginBitmapRender(tile.mSurface,tint); + if (hardwareSurface!=tile.mSurface || hardwareTint!=tint) + { + if (hardwareSurface) + hardware->EndBitmapRender(); + + hardwareSurface = tile.mSurface; + hardwareTint = tint; + hardware->BeginBitmapRender(tile.mSurface,tint); + } hardware->RenderBitmap(tile.mRect, (int)p.x, (int)p.y); } else @@ -1475,7 +1483,7 @@ void TextField::Render( const RenderTarget &inTarget, const RenderState &inState } - if (hardware) + if (hardwareSurface) hardware->EndBitmapRender(); } diff --git a/project/src/common/Tilesheet.cpp b/project/src/common/Tilesheet.cpp index 3d811d458..02d476065 100644 --- a/project/src/common/Tilesheet.cpp +++ b/project/src/common/Tilesheet.cpp @@ -12,7 +12,7 @@ Tilesheet::Tilesheet(int inWidth,int inHeight,PixelFormat inFormat, bool inInitR mCurrentY = 0; mMaxHeight = 0; mSheet = new SimpleSurface(inWidth,inHeight,inFormat); - + mSheet->IncRef(); } Tilesheet::Tilesheet(Surface *inSurface,bool inInitRef) : Object(inInitRef) diff --git a/project/src/platform/ios/UIStageView.mm b/project/src/platform/ios/UIStageView.mm index 95a31a219..f661435de 100644 --- a/project/src/platform/ios/UIStageView.mm +++ b/project/src/platform/ios/UIStageView.mm @@ -142,7 +142,6 @@ public: int Width() const { return mWidth; } int Height() const { return mHeight; } PixelFormat Format() const { return pfXRGB; } - AlphaMode GetAlphaMode() const { return amStraight; } const uint8 *GetBase() const { return (const uint8 *)mBuffer; } int GetStride() const { return mWidth*4; } void Clear(uint32 inColour,const lime::Rect *inRect) diff --git a/project/src/renderer/common/HardwareSurface.cpp b/project/src/renderer/common/HardwareSurface.cpp index cdb9c5476..0d1aeb8da 100644 --- a/project/src/renderer/common/HardwareSurface.cpp +++ b/project/src/renderer/common/HardwareSurface.cpp @@ -6,7 +6,6 @@ namespace lime { HardwareSurface::HardwareSurface (HardwareContext *inContext) { - mAlphaMode = amUnknown; mHardware = inContext; mHardware->IncRef (); @@ -24,7 +23,6 @@ namespace lime { // This is not really a clone... Surface *copy = new HardwareSurface (mHardware); - copy->setAlphaMode (mAlphaMode); copy->IncRef (); return copy; diff --git a/project/src/renderer/common/SimpleSurface.cpp b/project/src/renderer/common/SimpleSurface.cpp index 58015172e..c8a94748a 100644 --- a/project/src/renderer/common/SimpleSurface.cpp +++ b/project/src/renderer/common/SimpleSurface.cpp @@ -12,7 +12,6 @@ namespace lime { mTexture = 0; mPixelFormat = inPixelFormat; mGPUPixelFormat = inPixelFormat; - mAlphaMode = amUnknown; if (inGPUFormat == -1) { @@ -653,8 +652,6 @@ namespace lime { if (!mBase) return; - if (mAlphaMode == amIgnore || mAlphaMode == amPremultiplied) - return; Rect r = Rect (0, 0, mWidth, mHeight); mVersion++; if (mTexture) @@ -686,8 +683,6 @@ namespace lime { } - mAlphaMode = amPremultiplied; - } @@ -1011,8 +1006,6 @@ namespace lime { if (!mBase) return; - if (mAlphaMode == amIgnore || mAlphaMode == amStraight) - return; Rect r = Rect (0, 0, mWidth, mHeight); mVersion++; if (mTexture) @@ -1044,8 +1037,6 @@ namespace lime { } - mAlphaMode = amStraight; - } diff --git a/project/src/renderer/opengl/OpenGL2Context.cpp b/project/src/renderer/opengl/OpenGL2Context.cpp deleted file mode 100644 index ffa66c615..000000000 --- a/project/src/renderer/opengl/OpenGL2Context.cpp +++ /dev/null @@ -1,256 +0,0 @@ -#include "renderer/opengl/OpenGL2Context.h" - - -namespace lime { - - - OpenGL2Context::OpenGL2Context (WinDC inDC, GLCtx inOGLCtx) : OpenGLContext (inDC, inOGLCtx) { - - mIsRadial = false; - - for (int i = 0; i < gpuSIZE; i++) - mProg[i] = 0; - - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - mBitmapTrans[i][j] = mTrans[i][j] = (i == j); - //mBitmapTrans[2][2] = 0.0; - - } - - - OpenGL2Context::~OpenGL2Context () { - - for (int i = 0; i < gpuSIZE; i++) - delete mProg[i]; - - } - - - void OpenGL2Context::CombineModelView (const Matrix &inModelView) { - - mTrans[0][0] = inModelView.m00 * mScaleX; - mTrans[0][1] = inModelView.m01 * mScaleX; - mTrans[0][2] = 0; - mTrans[0][3] = inModelView.mtx * mScaleX + mOffsetX; - - mTrans[1][0] = inModelView.m10 * mScaleY; - mTrans[1][1] = inModelView.m11 * mScaleY; - mTrans[1][2] = 0; - mTrans[1][3] = inModelView.mty * mScaleY + mOffsetY; - - } - - - void OpenGL2Context::FinishBitmapRender () { - - // TODO: Need replacement call for GLES2 - //#ifndef LIME_FORCE_GLES2 - //glDisableClientState(GL_TEXTURE_COORD_ARRAY); - //#endif - - } - - - void OpenGL2Context::FinishDrawing () { - - if (mCurrentProg) - mCurrentProg->finishDrawing (); - - } - - - void OpenGL2Context::OnBeginRender () {} - - - void OpenGL2Context::PopBitmapMatrix () {} - - - void OpenGL2Context::PrepareBitmapRender () { - - GPUProgID id = mBitmapSurface->BytesPP () == 1 ? gpuBitmapAlpha : gpuBitmap; - if (!mProg[id]) - mProg[id] = GPUProg::create (id, mAlphaMode); - mCurrentProg = mProg[id]; - if (!mCurrentProg) - return; - - mCurrentProg->bind (); - mCurrentProg->setTint (mTint); - mBitmapSurface->Bind (*this, 0); - mCurrentProg->setTransform (mBitmapTrans); - // TODO: Need replacement call for GLES2 - //#ifndef LIME_FORCE_GLES2 - //glEnableClientState(GL_TEXTURE_COORD_ARRAY); - //#endif - - } - - - bool OpenGL2Context::PrepareDrawing () { - - GPUProgID id = gpuNone; - - if (mTexCoords) { - - if (mIsRadial) { - - if (mRadialFocus != 0) { - - id = gpuRadialFocusGradient; - - } else { - - id = gpuRadialGradient; - - } - - } else if (mColourTransform && !mColourTransform->IsIdentity ()) { - - id = gpuTextureTransform; - - } else if (mColourArray) { - - id = gpuTextureColourArray; - - } else { - - id = gpuTexture; - - } - - } else { - - if (mColourArray) { - - if (mColourTransform && !mColourTransform->IsIdentity ()) { - - id = gpuColourTransform; - - } else { - - id = gpuColour; - - } - - } else { - - id = gpuSolid; - - } - - } - - if (id == gpuNone) - return false; - - if (!mProg[id]) - mProg[id] = GPUProg::create (id, mAlphaMode); - - if (!mProg[id]) - return false; - - GPUProg *prog = mProg[id]; - mCurrentProg = prog; - prog->bind (); - - prog->setPositionData (mPosition, mPositionPerspective); - prog->setTransform (mTrans); - - if (mTexCoords) { - - prog->setTexCoordData (mTexCoords); - mTextureSurface->Bind (*this, 0); - - } - - if (mColourArray) - prog->setColourData (mColourArray); - - if (mColourTransform) - prog->setColourTransform (mColourTransform); - - if (id == gpuRadialFocusGradient) - prog->setGradientFocus (mRadialFocus); - - return true; - - } - - - void OpenGL2Context::PushBitmapMatrix () {} - - - void OpenGL2Context::SetBitmapData (const float *inPos, const float *inTex) { - - mCurrentProg->setPositionData (inPos, false); - mCurrentProg->setTexCoordData (inTex); - - } - - - void OpenGL2Context::SetColourArray (const int *inData) { - - mColourArray = inData; - - } - - - void OpenGL2Context::SetModulatingTransform (const ColorTransform *inTransform) { - - mColourTransform = inTransform; - - } - - - void OpenGL2Context::setOrtho (float x0, float x1, float y0, float y1) { - - mScaleX = 2.0 / (x1 - x0); - mScaleY = 2.0 / (y1 - y0); - mOffsetX = (x0 + x1) / (x0 - x1); - mOffsetY = (y0 + y1) / (y0 - y1); - mModelView = Matrix (); - - mBitmapTrans[0][0] = mScaleX; - mBitmapTrans[0][3] = mOffsetX; - mBitmapTrans[1][1] = mScaleY; - mBitmapTrans[1][3] = mOffsetY; - - CombineModelView (mModelView); - - } - - - void OpenGL2Context::SetPositionData (const float *inData,bool inPerspective) { - - mPosition = inData; - mPositionPerspective = inPerspective; - - } - - - void OpenGL2Context::SetRadialGradient (bool inIsRadial, float inFocus) { - - mIsRadial = inIsRadial; - mRadialFocus = inFocus; - - } - - - void OpenGL2Context::SetSolidColour (unsigned int col) { - - if (mCurrentProg) - mCurrentProg->setTint (col); - - } - - - void OpenGL2Context::SetTexture (Surface *inSurface, const float *inTexCoords) { - - mTextureSurface = inSurface; - mTexCoords = inTexCoords; - - } - - -} diff --git a/project/src/renderer/opengl/OpenGLContext.cpp b/project/src/renderer/opengl/OpenGLContext.cpp index 9869968c0..94377c8af 100644 --- a/project/src/renderer/opengl/OpenGLContext.cpp +++ b/project/src/renderer/opengl/OpenGLContext.cpp @@ -2,7 +2,6 @@ int sgDrawCount = 0; -int sgBufferCount = 0; int sgDrawBitmap = 0; @@ -17,22 +16,11 @@ namespace lime { mWidth = 0; mHeight = 0; mLineWidth = -1; - mPointsToo = true; - mBitmapSurface = 0; mBitmapTexture = 0; - mUsingBitmapMatrix = false; mLineScaleNormal = -1; mLineScaleV = -1; mLineScaleH = -1; - mPointSmooth = true; - mColourArrayEnabled = false; mThreadId = GetThreadId (); - mAlphaMode = amUnknown; - - const char *str = (const char *)glGetString (GL_VENDOR); - - if (str && !strncmp (str, "Intel", 5)) - mPointSmooth = false; #if defined(LIME_GLES) mQuality = sqLow; @@ -40,31 +28,77 @@ namespace lime { mQuality = sqBest; #endif + for (int i = 0; i < PROG_COUNT; i++) { + + mProg[i] = 0; + + } + + for (int i = 0; i < 4; i++) { + + for (int j = 0; j < 4; j++) { + + mBitmapTrans[i][j] = mTrans[i][j] = (i == j); + + } + + } + + mBitmapBuffer.mElements.resize (1); + DrawElement &e = mBitmapBuffer.mElements[0]; + memset (&e, 0, sizeof (DrawElement)); + e.mCount = 0; + e.mFlags = DRAW_HAS_TEX; + e.mPrimType = ptTriangles; + e.mVertexOffset = 0; + e.mColour = 0xff000000; + e.mTexOffset = sizeof (float) * 2; + e.mStride = sizeof (float) * 4; + } - OpenGLContext::~OpenGLContext () {} + OpenGLContext::~OpenGLContext () { + + for (int i = 0; i < PROG_COUNT; i++) { + + delete mProg[i]; + + } + + } void OpenGLContext::BeginBitmapRender (Surface *inSurface, uint32 inTint, bool inRepeat, bool inSmooth) { - if (!mUsingBitmapMatrix) { + mBitmapBuffer.mArray.resize (0); + mBitmapBuffer.mRendersWithoutVbo = -999; + DrawElement &e = mBitmapBuffer.mElements[0]; + e.mCount = 0; + + e.mColour = inTint; + if (e.mSurface) { - mUsingBitmapMatrix = true; - PushBitmapMatrix (); + e.mSurface->DecRef (); + } + + e.mSurface = inSurface; + e.mSurface->IncRef (); + e.mFlags = (e.mFlags & ~(DRAW_BMP_REPEAT|DRAW_BMP_SMOOTH)); + + if (inRepeat) { + + e.mFlags |= DRAW_BMP_REPEAT; } - if (mBitmapSurface == inSurface && mTint == inTint) - return; + if (inSmooth) { + + e.mFlags |= DRAW_BMP_SMOOTH; + + } - mTint = inTint; - mBitmapSurface = inSurface; - inSurface->Bind (*this, 0); mBitmapTexture = inSurface->GetOrCreateTexture (*this); - mBitmapTexture->BindFlags (inRepeat, inSmooth); - - PrepareBitmapRender (); } @@ -88,39 +122,28 @@ namespace lime { } + if (mZombieVbos.size ()) { + + glDeleteTextures (mZombieVbos.size (), &mZombieVbos[0]); + mZombieVbos.resize (0); + + } + // Force dirty mViewport.w = -1; SetViewport (inRect); - //#ifndef LIME_FORCE_GLES2 glEnable (GL_BLEND); - //#endif - - if (mAlphaMode == amPremultiplied) - glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - else - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #ifdef WEBOS glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); #endif - #ifndef LIME_FORCE_GLES2 - if (mQuality >= sqHigh && mPointSmooth) - glEnable (GL_POINT_SMOOTH); - - if (mQuality >= sqBest) - glEnable (GL_LINE_SMOOTH); - #endif - mLineWidth = 99999; // printf("DrawArrays: %d, DrawBitmaps:%d Buffers:%d\n", sgDrawCount, sgDrawBitmap, sgBufferCount ); sgDrawCount = 0; sgDrawBitmap = 0; - sgBufferCount = 0; - - OnBeginRender (); } @@ -130,38 +153,25 @@ namespace lime { void OpenGLContext::Clear (uint32 inColour, const Rect *inRect) { Rect r = inRect ? *inRect : Rect (mWidth, mHeight); + glViewport (r.x, mHeight - r.y1 (), r.w, r.h); + float alpha = ((inColour >> 24) & 0xFF) / 255.0; + float red = ((inColour >> 16) & 0xFF) / 255.0; + float green = ((inColour >> 8) & 0xFF) / 255.0; + float blue = (inColour & 0xFF) / 255.0; + red *= alpha; + green *= alpha; + blue *= alpha; + if (r == Rect (mWidth, mHeight)) { - glClearColor ((GLclampf)(((inColour >> 16) & 0xff) / 255.0), (GLclampf)(((inColour >> 8) & 0xff) / 255.0), (GLclampf)(((inColour) & 0xff) / 255.0), (GLclampf)1.0); + glClearColor (red, green, blue, alpha ); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else { - #ifndef LIME_FORCE_GLES2 - - // TODO: Clear with a rect - // TODO: Need replacement call for GLES2 - glColor4f ((GLclampf)(((inColour >> 16) & 0xff) / 255.0), (GLclampf)(((inColour >> 8) & 0xff) / 255.0), (GLclampf)(((inColour) & 0xff) / 255.0), (GLclampf)1.0); - - glMatrixMode (GL_MODELVIEW); - glPushMatrix (); - glLoadIdentity (); - glMatrixMode (GL_PROJECTION); - glPushMatrix (); - glLoadIdentity (); - - glDisable (GL_TEXTURE_2D); - static GLfloat rect[4][2] = { { -2, -2 }, { 2, -2 }, { 2, 2 }, { -2, 2 } }; - glVertexPointer (2, GL_FLOAT, 0, rect[0]); - glDrawArrays (GL_TRIANGLE_FAN, 0, 4); - - glPopMatrix (); - glMatrixMode (GL_MODELVIEW); - glPopMatrix (); - - #endif + //printf(" - partial clear\n"); } @@ -176,20 +186,15 @@ namespace lime { void OpenGLContext::CombineModelView (const Matrix &inModelView) { - #ifndef LIME_FORCE_GLES2 + mTrans[0][0] = inModelView.m00 * mScaleX; + mTrans[0][1] = inModelView.m01 * mScaleX; + mTrans[0][2] = 0; + mTrans[0][3] = inModelView.mtx * mScaleX + mOffsetX; - // Do not combine ModelView and Projection in fixed-function - float matrix[] = { - - mModelView.m00, mModelView.m10, 0, 0, - mModelView.m01, mModelView.m11, 0, 0, - 0, 0, 1, 0, - mModelView.mtx, mModelView.mty, 0, 1 - - }; - - glLoadMatrixf (matrix); - #endif + mTrans[1][0] = inModelView.m10 * mScaleY; + mTrans[1][1] = inModelView.m11 * mScaleY; + mTrans[1][2] = 0; + mTrans[1][3] = inModelView.mty * mScaleY + mOffsetY; } @@ -217,35 +222,50 @@ namespace lime { } } - - - void OpenGLContext::EndBitmapRender () { + + + void OpenGLContext::DestroyVbo (unsigned int inVbo) { - if (mUsingBitmapMatrix) { + if (!IsMainThread ()) { - mUsingBitmapMatrix = false; - PopBitmapMatrix (); + mZombieVbos.push_back (inVbo); + + } else { + + glDeleteBuffers (1, &inVbo); } - mBitmapTexture = 0; - mBitmapSurface = 0; - FinishBitmapRender (); - } - void OpenGLContext::EndRender () {} - - - void OpenGLContext::FinishBitmapRender () { + void OpenGLContext::EndBitmapRender () { + + DrawElement &e = mBitmapBuffer.mElements[0]; + + if (e.mCount) { + + RenderData (mBitmapBuffer, 0, mBitmapTrans); + e.mCount = 0; + + } + + if (e.mSurface) { + + e.mSurface->DecRef (); + e.mSurface = 0; + + } + + mBitmapBuffer.mArray.resize (0); + mBitmapTexture = 0; + + } + + + void OpenGLContext::EndRender () { + - #ifndef LIME_FORCE_GLES2 - glDisable (GL_TEXTURE_2D); - #ifdef LIME_DITHER - glEnable (GL_DITHER); - #endif - #endif } @@ -263,77 +283,16 @@ namespace lime { } - void OpenGLContext::FinishDrawing () { + void OpenGLContext::Render (const RenderState &inState, const HardwareData &inData) { - SetColourArray (0); + if (!inData.mArray.size ()) { + + return; + + } - } - - - void OpenGLContext::OnBeginRender () { - - #ifndef LIME_FORCE_GLES2 - glEnableClientState (GL_VERTEX_ARRAY); - #endif - - } - - - void OpenGLContext::PopBitmapMatrix () { - - #ifndef LIME_FORCE_GLES2 - glPopMatrix (); - #endif - - } - - - void OpenGLContext::PrepareBitmapRender () { - - #ifndef LIME_FORCE_GLES2 - float a = (float)((mTint >> 24) & 0xFF) * one_on_255; - float c0 = (float)((mTint >> 16) & 0xFF) * one_on_255; - float c1 = (float)((mTint >> 8) & 0xFF) * one_on_255; - float c2 = (float)(mTint & 0xFF) * one_on_255; - if (mAlphaMode == amPremultiplied) - glColor4f (c0 * a, c1 * a, c2 * a, a); - else - glColor4f (c0, c1, c2, a); - glEnable (GL_TEXTURE_2D); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - #ifdef LIME_DITHER - if (!inSmooth) - glDisable (GL_DITHER); - #endif - #endif - - } - - - bool OpenGLContext::PrepareDrawing () { - - return true; - - } - - - void OpenGLContext::PushBitmapMatrix () { - - #ifndef LIME_FORCE_GLES2 - glPushMatrix (); - glLoadIdentity (); - #endif - - } - - - void OpenGLContext::Render (const RenderState &inState, const HardwareCalls &inCalls) { - - //#ifndef LIME_FORCE_GLES2 - glEnable (GL_BLEND); - //#endif SetViewport (inState.mClipRect); - + if (mModelView != *inState.mTransform.mMatrix) { mModelView = *inState.mTransform.mMatrix; @@ -344,416 +303,362 @@ namespace lime { } - uint32 last_col = 0; + const ColorTransform *ctrans = inState.mColourTransform; - for (int c = 0; c < inCalls.size (); c++) { + if (ctrans && ctrans->IsIdentity ()) { - HardwareArrays &arrays = *inCalls[c]; - DrawElements &elements = arrays.mElements; - if (elements.empty ()) - continue; - - Vertices &vert = arrays.mVertices; - Vertices &tex_coords = arrays.mTexCoords; - bool persp = arrays.mFlags & HardwareArrays::PERSPECTIVE; - - if (arrays.mFlags & HardwareArrays::BM_ADD) { - - glBlendFunc (GL_SRC_ALPHA, GL_ONE); - - } else if (arrays.mFlags & HardwareArrays::BM_MULTIPLY) { - - glBlendFunc (GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); - - } else if (arrays.mFlags & HardwareArrays::BM_SCREEN) { - - glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR); - - } else if (arrays.mFlags & HardwareArrays::AM_PREMULTIPLIED) { - - //printf("Premultiplied\n"); - mAlphaMode = amPremultiplied; - glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - } else { - - //printf("Straight\n"); - mAlphaMode = amStraight; - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - } - - #ifdef LIME_USE_VBO - if (!arrays.mVertexBO) { - - glGenBuffers (1, &arrays.mVertexBO); - glBindBuffer (GL_ARRAY_BUFFER, arrays.mVertexBO); - glBufferData (GL_ARRAY_BUFFER, sizeof(float) * (persp ? 4 : 2) * vert.size (), &vert[0].x, GL_STATIC_DRAW); - - } else { - - glBindBuffer (GL_ARRAY_BUFFER, arrays.mVertexBO); - - } - - glVertexPointer (persp ? 4 : 2, GL_FLOAT, 0, 0); - glBindBuffer (GL_ARRAY_BUFFER, 0); - #else - SetPositionData (&vert[0].x, persp); - #endif - - Texture *boundTexture = 0; - bool tex = arrays.mSurface && tex_coords.size (); - if (tex) { - - boundTexture = arrays.mSurface->GetOrCreateTexture (*this); - SetTexture (arrays.mSurface, &tex_coords[0].x); - last_col = -1; - SetModulatingTransform (inState.mColourTransform); - - if (arrays.mFlags & HardwareArrays::RADIAL) { - - float focus = ((arrays.mFlags & HardwareArrays::FOCAL_MASK) >> 8) / 256.0; - if (arrays.mFlags & HardwareArrays::FOCAL_SIGN) - focus = -focus; - SetRadialGradient (true, focus); - - } else { - - SetRadialGradient (0, 0); - - } - - } else { - - boundTexture = 0; - SetTexture (0, 0); - SetModulatingTransform (0); - - } - - if (arrays.mColours.size () == vert.size ()) { - - SetColourArray (&arrays.mColours[0]); - SetModulatingTransform (inState.mColourTransform); - - } else { - - SetColourArray (0); - - } - - int n = elements.size (); - if (!PrepareDrawing ()) - n = 0; - - sgBufferCount++; - for (int e = 0; e < n; e++) { - - DrawElement draw = elements[e]; - - if (boundTexture) { - - boundTexture->BindFlags (draw.mBitmapRepeat, draw.mBitmapSmooth); - #ifndef LIME_FORCE_GLES2 - #ifdef LIME_DITHER - if (!inSmooth) - glDisable (GL_DITHER); - #endif - #endif - - } else { - - int col = inState.mColourTransform->Transform (draw.mColour); - if (c == 0 || last_col != col) { - - last_col = col; - SetSolidColour (col); - - } - - } - - if ((draw.mPrimType == ptLineStrip || draw.mPrimType == ptPoints || draw.mPrimType == ptLines) && draw.mCount > 1) { - - if (draw.mWidth < 0) { - - SetLineWidth (1.0); - - } else if (draw.mWidth == 0) { - - SetLineWidth (0.0); - - } else { - - switch (draw.mScaleMode) { - - case ssmNone: - SetLineWidth (draw.mWidth); - break; - - case ssmNormal: - case ssmOpenGL: - if (mLineScaleNormal < 0) - mLineScaleNormal = sqrt (0.5 * ((mModelView.m00 * mModelView.m00) + (mModelView.m01 * mModelView.m01) + (mModelView.m10 * mModelView.m10) + (mModelView.m11 * mModelView.m11))); - SetLineWidth (draw.mWidth * mLineScaleNormal); - break; - - case ssmVertical: - if (mLineScaleV < 0) - mLineScaleV = sqrt ((mModelView.m00 * mModelView.m00) + (mModelView.m01 * mModelView.m01)); - SetLineWidth (draw.mWidth * mLineScaleV); - break; - - case ssmHorizontal: - if (mLineScaleH <0) - mLineScaleH = sqrt ((mModelView.m10 * mModelView.m10) + (mModelView.m11 * mModelView.m11)); - SetLineWidth (draw.mWidth * mLineScaleH); - break; - - } - - } - - if (mPointsToo && mLineWidth > 1.5 && draw.mPrimType != ptLines) - glDrawArrays (GL_POINTS, draw.mFirst, draw.mCount); - - } - - //printf("glDrawArrays %d : %d x %d\n", draw.mPrimType, draw.mFirst, draw.mCount ); - - sgDrawCount++; - glDrawArrays (sgOpenglType[draw.mPrimType], draw.mFirst, draw.mCount); - - //#ifndef LIME_FORCE_GLES2 - #ifdef LIME_DITHER - if (boundTexture && !draw.mBitmapSmooth) - glEnable (GL_DITHER); - #endif - //#endif - - } - - FinishDrawing (); + ctrans = 0; } + RenderData (inData, ctrans, mTrans); + } void OpenGLContext::RenderBitmap (const Rect &inSrc, int inX, int inY) { - UserPoint vertex[4]; + DrawElement &e = mBitmapBuffer.mElements[0]; + mBitmapBuffer.mArray.resize ((e.mCount + 6) * e.mStride); + UserPoint *p = (UserPoint *)&mBitmapBuffer.mArray[e.mCount * e.mStride]; + e.mCount += 6; + + UserPoint corners[4]; UserPoint tex[4]; for (int i = 0; i < 4; i++) { - UserPoint t (inSrc.x + ((i & 1) ? inSrc.w : 0), inSrc.y + ((i > 1) ? inSrc.h : 0)); - tex[i] = mBitmapTexture->PixelToTex (t); - vertex[i] = UserPoint (inX + ((i & 1) ? inSrc.w : 0), inY + ((i > 1) ? inSrc.h : 0)); + corners[i] = UserPoint (inX + ((i & 1) ? inSrc.w : 0), inY + ((i > 1) ? inSrc.h : 0)); + tex[i] = mBitmapTexture->PixelToTex (UserPoint (inSrc.x + ((i & 1) ? inSrc.w : 0), inSrc.y + ((i > 1) ? inSrc.h : 0))); } - SetBitmapData (&vertex[0].x, &tex[0].x); + *p++ = corners[0]; + *p++ = tex[0]; + *p++ = corners[1]; + *p++ = tex[1]; + *p++ = corners[2]; + *p++ = tex[2]; - glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - sgDrawBitmap++; + *p++ = corners[1]; + *p++ = tex[1]; + *p++ = corners[2]; + *p++ = tex[2]; + *p++ = corners[3]; + *p++ = tex[3]; } - void OpenGLContext::SetBitmapData (const float *inPos, const float *inTex) { + void OpenGLContext::RenderData (const HardwareData &inData, const ColorTransform *ctrans, const Trans4x4 &inTrans) { - #ifndef LIME_FORCE_GLES2 - glVertexPointer (2, GL_FLOAT, 0, inPos); - glTexCoordPointer (2, GL_FLOAT, 0, inTex); - #endif + const uint8 *data = 0; - } - - - void OpenGLContext::SetColourArray (const int *inData) { - - #ifndef LIME_FORCE_GLES2 - if (inData) { + if (inData.mVertexBo) { - mColourArrayEnabled = true; - glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (4, GL_UNSIGNED_BYTE, 0, inData); + glBindBuffer (GL_ARRAY_BUFFER, inData.mVertexBo); - } else if (mColourArrayEnabled) { + } else { - mColourArrayEnabled = false; - glDisableClientState (GL_COLOR_ARRAY); + data = &inData.mArray[0]; + inData.mRendersWithoutVbo++; + + if (inData.mRendersWithoutVbo > 4) { + + glGenBuffers (1, &inData.mVertexBo); + inData.mVboOwner = this; + IncRef (); + glBindBuffer (GL_ARRAY_BUFFER, inData.mVertexBo); + // printf ("VBO DATA %d\n", inData.mArray.size ()); + glBufferData (GL_ARRAY_BUFFER, inData.mArray.size (), data, GL_STATIC_DRAW); + data = 0; + + } } - #endif - } - - - void OpenGLContext::SetLineWidth (double inWidth) { - - if (inWidth != mLineWidth) { + GPUProg *lastProg = 0; + + for (int e = 0; e < inData.mElements.size (); e++) { - double w = inWidth; - #ifndef LIME_FORCE_GLES2 - if (mQuality >= sqBest) { + const DrawElement &element = inData.mElements[e]; + int n = element.mCount; + + if (!n) { - if (w > 1) { + continue; + + } + + switch (element.mBlendMode) { + + case bmAdd: - glDisable (GL_LINE_SMOOTH); + glBlendFunc (GL_SRC_ALPHA, GL_ONE); + break; + + case bmMultiply: + + glBlendFunc (GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); + break; + + case bmScreen: + + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR); + break; + + default: + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + + } + + int progId = 0; + + if ((element.mFlags & DRAW_HAS_TEX) && element.mSurface) { + + progId |= PROG_TEXTURE; + if (element.mSurface->BytesPP () == 1) { + + progId |= PROG_ALPHA_TEXTURE; + + } + + } + + if (element.mFlags & DRAW_HAS_COLOUR) { + + progId |= PROG_COLOUR_PER_VERTEX; + + } + + if (element.mFlags & DRAW_HAS_NORMAL) { + + progId |= PROG_NORMAL_DATA; + + } + + if (element.mFlags & DRAW_RADIAL) { + + progId |= PROG_RADIAL; + if (element.mRadialPos != 0) { + + progId |= PROG_RADIAL_FOCUS; + + } + + } + + if (ctrans || element.mColour != 0xFFFFFFFF) { + + progId |= PROG_TINT; + if (ctrans && ctrans->HasOffset ()) + progId |= PROG_COLOUR_OFFSET; + + } + + bool persp = element.mFlags & DRAW_HAS_PERSPECTIVE; + GPUProg *prog = mProg[progId]; + + if (!prog) { + + mProg[progId] = prog = GPUProg::create (progId); + + } + + if (!prog) { + + continue; + + } + + if (prog != lastProg) { + + if (lastProg) { + + lastProg->disableSlots (); + + } + + prog->bind (); + prog->setTransform (inTrans); + lastProg = prog; + + } + + int stride = element.mStride; + if (prog->vertexSlot >= 0) { + + glVertexAttribPointer (prog->vertexSlot, persp ? 4 : 2 , GL_FLOAT, GL_FALSE, stride, data + element.mVertexOffset); + glEnableVertexAttribArray (prog->vertexSlot); + + } + + if (prog->textureSlot >= 0) { + + glVertexAttribPointer (prog->textureSlot, 2 , GL_FLOAT, GL_FALSE, stride, data + element.mTexOffset); + glEnableVertexAttribArray (prog->textureSlot); + + if (element.mSurface) { + + Texture *boundTexture = element.mSurface->GetOrCreateTexture (*this); + element.mSurface->Bind (*this, 0); + boundTexture->BindFlags (element.mFlags & DRAW_BMP_REPEAT, element.mFlags & DRAW_BMP_SMOOTH); + + } + + } + + if (prog->colourSlot >= 0) { + + glVertexAttribPointer (prog->colourSlot, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, data + element.mColourOffset); + glEnableVertexAttribArray (prog->colourSlot); + + } + + if (prog->normalSlot >= 0) { + + glVertexAttribPointer (prog->normalSlot, 2, GL_FLOAT, GL_FALSE, stride, data + element.mNormalOffset); + glEnableVertexAttribArray (prog->normalSlot); + + } + + if (element.mFlags & DRAW_RADIAL) { + + prog->setGradientFocus (element.mRadialPos * one_on_256); + + } + + if (progId & (PROG_TINT | PROG_COLOUR_OFFSET)) { + + prog->setColourTransform (ctrans, element.mColour); + + } + + if ((element.mPrimType == ptLineStrip || element.mPrimType == ptPoints || element.mPrimType == ptLines) && element.mCount > 1) { + + if (element.mWidth < 0) { + + SetLineWidth (1.0); + + } else if (element.mWidth == 0) { + + SetLineWidth (0.0); } else { - w = 1; - if (inWidth == 0) { + switch (element.mScaleMode) { - glDisable (GL_LINE_SMOOTH); + case ssmNone: SetLineWidth (element.mWidth); break; + + case ssmNormal: + case ssmOpenGL: + + if (mLineScaleNormal < 0) { + + mLineScaleNormal = sqrt (0.5 * ((mModelView.m00 * mModelView.m00) + (mModelView.m01 * mModelView.m01) + (mModelView.m10 * mModelView.m10) + (mModelView.m11 * mModelView.m11))); + + } + + SetLineWidth (element.mWidth * mLineScaleNormal); + break; - } else { + case ssmVertical: + + if (mLineScaleV < 0) { + + mLineScaleV = sqrt ((mModelView.m00 * mModelView.m00) + (mModelView.m01 * mModelView.m01)); + + } + + SetLineWidth (element.mWidth * mLineScaleV); + break; - glEnable (GL_LINE_SMOOTH); + case ssmHorizontal: + + if (mLineScaleH<0) { + + mLineScaleH = sqrt ((mModelView.m10 * mModelView.m10) + (mModelView.m11 * mModelView.m11)); + + } + + SetLineWidth (element.mWidth * mLineScaleH); + break; } } } - #endif + + //printf("glDrawArrays %d : %d x %d\n", element.mPrimType, element.mFirst, element.mCount ); + sgDrawCount++; + glDrawArrays (sgOpenglType[element.mPrimType], 0, element.mCount); + + } + + if (lastProg) { + + lastProg->disableSlots (); + + } + + if (inData.mVertexBo) { + + glBindBuffer (GL_ARRAY_BUFFER, 0); + + } + + } + + + inline void OpenGLContext::SetLineWidth (double inWidth) { + + if (inWidth != mLineWidth) { + + // TODO mQuality -> tessellate_lines/tessellate_lines_aa mLineWidth = inWidth; - glLineWidth (w); - - // TODO: Need replacement call for GLES2? - #ifndef LIME_FORCE_GLES2 - if (mPointsToo) - glPointSize (inWidth); - #endif + glLineWidth (inWidth); } } - void OpenGLContext::SetModulatingTransform (const ColorTransform *inTransform) { - - #ifndef LIME_FORCE_GLES2 - if (inTransform) { - if (mAlphaMode == amPremultiplied) - glColor4f (inTransform->redMultiplier * inTransform->alphaMultiplier, inTransform->greenMultiplier * inTransform->alphaMultiplier, inTransform->blueMultiplier * inTransform->alphaMultiplier, inTransform->alphaMultiplier); - else - glColor4f (inTransform->redMultiplier, inTransform->greenMultiplier, inTransform->blueMultiplier, inTransform->alphaMultiplier); - } - #endif - - } - - - void OpenGLContext::setOrtho (float x0,float x1, float y0, float y1) { - - #ifndef LIME_FORCE_GLES2 - - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - - #if defined (LIME_GLES) - glOrthof (x0, x1, y0, y1, -1, 1); - #else - glOrtho (x0, x1, y0, y1, -1, 1); - #endif - - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - - #endif + void OpenGLContext::setOrtho (float x0, float x1, float y0, float y1) { + mScaleX = 2.0 / (x1 - x0); + mScaleY = 2.0 / (y1 - y0); + mOffsetX = (x0 + x1) / (x0 - x1); + mOffsetY = (y0 + y1) / (y0 - y1); mModelView = Matrix (); - } - - - void OpenGLContext::SetPositionData (const float *inData, bool inPerspective) { + mBitmapTrans[0][0] = mScaleX; + mBitmapTrans[0][3] = mOffsetX; + mBitmapTrans[1][1] = mScaleY; + mBitmapTrans[1][3] = mOffsetY; - #ifndef LIME_FORCE_GLES2 - glVertexPointer (inPerspective ? 4 : 2, GL_FLOAT, 0, inData); - #endif + CombineModelView (mModelView); - } + } void OpenGLContext::SetQuality (StageQuality inQ) { - #ifndef LIME_FORCE_GLES2 - //inQ = sqMedium; if (inQ != mQuality) { mQuality = inQ; - if (mQuality >= sqHigh) { - - if (mPointSmooth) - glEnable (GL_POINT_SMOOTH); - - } else { - - glDisable (GL_POINT_SMOOTH); - - } - - if (mQuality >= sqBest) - glEnable (GL_LINE_SMOOTH); - else - glDisable (GL_LINE_SMOOTH); mLineWidth = 99999; } - #endif - - } - - - void OpenGLContext::SetRadialGradient (bool inIsRadial, float inFocus) {}; - - - void OpenGLContext::SetSolidColour (unsigned int col) { - - #ifndef LIME_FORCE_GLES2 - float a = (float)((col >> 24) & 0xFF) * one_on_255; - float c0 = (float)((col >> 16) & 0xFF) * one_on_255; - float c1 = (float)((col >> 8) & 0xFF) * one_on_255; - float c2 = (float)(col & 0xFF) * one_on_255; - if (mAlphaMode == amPremultiplied) - glColor4f (c0 * a, c1 * a,c2 * a, a); - else - glColor4f (c0, c1, c2, a); - #endif - - } - - - void OpenGLContext::SetTexture (Surface *inSurface, const float *inTexCoords) { - - #ifndef LIME_FORCE_GLES2 - if (!inSurface) { - - glDisable (GL_TEXTURE_2D); - glDisableClientState (GL_TEXTURE_COORD_ARRAY); - - } else { - - glEnable (GL_TEXTURE_2D); - inSurface->Bind (*this, 0); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, 0, inTexCoords); - - } - #endif } void OpenGLContext::SetViewport (const Rect &inRect) { - + if (inRect != mViewport) { setOrtho (inRect.x, inRect.x1 (), inRect.y1 (), inRect.y); @@ -763,18 +668,17 @@ namespace lime { } } - - + + void OpenGLContext::SetWindowSize (int inWidth, int inHeight) { mWidth = inWidth; mHeight = inHeight; - #ifdef ANDROID - //__android_log_print(ANDROID_LOG_ERROR, "lime", "SetWindowSize %d %d", inWidth, inHeight); + //__android_log_print(ANDROID_LOG_ERROR, "Lime", "SetWindowSize %d %d", inWidth, inHeight); #endif } - + } diff --git a/project/src/renderer/opengl/OpenGLInit.cpp b/project/src/renderer/opengl/OpenGLInit.cpp index 299427247..a5aa1cc50 100644 --- a/project/src/renderer/opengl/OpenGLInit.cpp +++ b/project/src/renderer/opengl/OpenGLInit.cpp @@ -7,7 +7,6 @@ #endif #include "renderer/opengl/OpenGLContext.h" -#include "renderer/opengl/OpenGL2Context.h" #include "renderer/opengl/OpenGLTexture.h" #ifdef TIZEN @@ -126,15 +125,15 @@ namespace lime { #endif #endif - if (shaders && HasShaderSupport ()) { + //if (shaders && HasShaderSupport ()) { //#ifdef TIZEN //AppLog ("Using OGL2\n"); //#endif //printf("Using OGL2\n"); - ctx = new OpenGL2Context ((WinDC)inWindow, (GLCtx)inGLCtx); + //ctx = new OpenGL2Context ((WinDC)inWindow, (GLCtx)inGLCtx); - } else { + //} else { //#ifdef TIZEN //AppLog ("Using OGL2\n"); @@ -142,7 +141,11 @@ namespace lime { //printf("Using OGL1\n"); ctx = new OpenGLContext ((WinDC)inWindow, (GLCtx)inGLCtx); - } + //} else { + + // return 0; + + //} InitExtensions (); return ctx; diff --git a/project/src/renderer/opengl/OpenGLProgram.cpp b/project/src/renderer/opengl/OpenGLProgram.cpp index f25908eef..137828482 100644 --- a/project/src/renderer/opengl/OpenGLProgram.cpp +++ b/project/src/renderer/opengl/OpenGLProgram.cpp @@ -1,5 +1,4 @@ #include "renderer/opengl/OGL.h" -#ifdef ALLOW_OGL2 #include "renderer/opengl/OpenGLProgram.h" @@ -11,16 +10,24 @@ namespace lime { const float one_on_255 = 1.0 / 255.0; - OpenGLProgram::OpenGLProgram (const char *inVertProg, const char *inFragProg, AlphaMode inAlphaMode) { + OpenGLProgram::OpenGLProgram (const std::string &inVertProg, const std::string &inFragProg) { mVertProg = inVertProg; mFragProg = inFragProg; - mAlphaMode = inAlphaMode; mVertId = 0; mFragId = 0; - mTexCoordSlot = -1; - mTextureSlot = -1; + + mImageSlot = -1; mColourTransform = 0; + + vertexSlot = -1; + textureSlot = -1; + normalSlot = -1; + colourSlot = -1; + + //printf("%s", inVertProg.c_str()); + //printf("%s", inFragProg.c_str()); + recreate (); } @@ -48,16 +55,6 @@ namespace lime { const char *source = inShader; GLuint shader = glCreateShader (inType); - #ifdef LIME_GLES - std::string sourceBuf; - if (inType == GL_FRAGMENT_SHADER) { - - sourceBuf = std::string ("precision mediump float;\n") + inShader; - source = sourceBuf.c_str (); - - } - #endif - glShaderSource (shader, 1, &source, 0); glCompileShader (shader); @@ -91,23 +88,38 @@ namespace lime { } - void OpenGLProgram::finishDrawing () { + void OpenGLProgram::disableSlots () { - if (mColourArraySlot >= 0) - glDisableVertexAttribArray (mColourArraySlot); + if (vertexSlot >= 0) { + + glDisableVertexAttribArray (vertexSlot); + + } - if (mTexCoordSlot >= 0) - glDisableVertexAttribArray (mTexCoordSlot); + if (normalSlot >= 0) { + + glDisableVertexAttribArray (normalSlot); + + } - if (mVertexSlot >= 0) - glDisableVertexAttribArray (mVertexSlot); + if (colourSlot >= 0) { + + glDisableVertexAttribArray (colourSlot); + + } + + if (textureSlot >= 0) { + + glDisableVertexAttribArray (textureSlot); + + } } int OpenGLProgram::getTextureSlot () { - return mTextureSlot; + return mImageSlot; } @@ -117,10 +129,10 @@ namespace lime { mContextVersion = gTextureContextVersion; mProgramId = 0; - mVertId = createShader (GL_VERTEX_SHADER, mVertProg); + mVertId = createShader (GL_VERTEX_SHADER, mVertProg.c_str ()); if (!mVertId) return; - mFragId = createShader (GL_FRAGMENT_SHADER, mFragProg); + mFragId = createShader (GL_FRAGMENT_SHADER, mFragProg.c_str ()); if (!mFragId) return; @@ -154,8 +166,8 @@ namespace lime { char *log = new char[logLen]; glGetProgramInfoLog (mProgramId, logLen, &logLen, log); ELOG ("----"); - ELOG ("VERT: %s", mVertProg); - ELOG ("FRAG: %s", mFragProg); + ELOG ("VERT: %s", mVertProg.c_str ()); + ELOG ("FRAG: %s", mFragProg.c_str ()); ELOG ("ERROR:\n%s\n", log); delete [] log; @@ -168,57 +180,58 @@ namespace lime { } - mVertexSlot = glGetAttribLocation (mProgramId, "aVertex"); - mTexCoordSlot = glGetAttribLocation (mProgramId, "aTexCoord"); + vertexSlot = glGetAttribLocation(mProgramId, "aVertex"); + textureSlot = glGetAttribLocation(mProgramId, "aTexCoord"); + colourSlot = glGetAttribLocation(mProgramId, "aColourArray"); + normalSlot = glGetAttribLocation(mProgramId, "aNormal"); + mTransformSlot = glGetUniformLocation (mProgramId, "uTransform"); - mTintSlot = glGetUniformLocation (mProgramId, "uTint"); - mColourArraySlot = glGetAttribLocation (mProgramId, "aColourArray"); - mTextureSlot = glGetUniformLocation (mProgramId, "uImage0"); + mImageSlot = glGetUniformLocation(mProgramId, "uImage0"); mColourOffsetSlot = glGetUniformLocation (mProgramId, "uColourOffset"); mColourScaleSlot = glGetUniformLocation (mProgramId, "uColourScale"); mFXSlot = glGetUniformLocation (mProgramId, "mFX"); mASlot = glGetUniformLocation (mProgramId, "mA"); mOn2ASlot = glGetUniformLocation (mProgramId, "mOn2A"); + glUseProgram (mProgramId); + + if (mImageSlot >= 0) { + + glUniform1i (mImageSlot, 0); + + } + } - void OpenGLProgram::setColourData (const int *inData) { + void OpenGLProgram::setColourTransform (const ColorTransform *inTransform, uint32 inColor) { - if (inData && mColourArraySlot >= 0) { + float rf, gf, bf, af; + + if (inColor == 0xFFFFFFFF) { - glVertexAttribPointer (mColourArraySlot, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, inData); - glEnableVertexAttribArray (mColourArraySlot); + rf = gf = bf = af = 1.0; - } else if (mColourArraySlot >= 0) { + } else { - glDisableVertexAttribArray (mColourArraySlot); + rf = ((inColor >> 16) & 0xFF) * one_on_255; + gf = ((inColor >> 8) & 0xFF) * one_on_255; + bf = (inColor & 0xFF) * one_on_255; + af = ((inColor >> 24) & 0xFF) * one_on_255; } - } - - - void OpenGLProgram::setColourTransform (const ColorTransform *inTransform) { - - mColourTransform = inTransform; if (inTransform && !inTransform->IsIdentity ()) { if (mColourOffsetSlot >= 0) { - if (mAlphaMode == amPremultiplied) - glUniform4f (mColourOffsetSlot, inTransform->redOffset * one_on_255 * inTransform->alphaMultiplier, inTransform->greenOffset * one_on_255 * inTransform->alphaMultiplier, inTransform->blueOffset * one_on_255 * inTransform->alphaMultiplier, inTransform->alphaOffset * one_on_255); - else - glUniform4f (mColourOffsetSlot, inTransform->redOffset * one_on_255, inTransform->greenOffset * one_on_255, inTransform->blueOffset * one_on_255, inTransform->alphaOffset * one_on_255); + glUniform4f (mColourOffsetSlot, inTransform->redOffset * one_on_255, inTransform->greenOffset * one_on_255, inTransform->blueOffset * one_on_255, inTransform->alphaOffset * one_on_255); } if (mColourScaleSlot >= 0) { - if (mAlphaMode == amPremultiplied) - glUniform4f (mColourScaleSlot, inTransform->redMultiplier * inTransform->alphaMultiplier, inTransform->greenMultiplier * inTransform->alphaMultiplier, inTransform->blueMultiplier * inTransform->alphaMultiplier, inTransform->alphaMultiplier); - else - glUniform4f (mColourScaleSlot, inTransform->redMultiplier, inTransform->greenMultiplier, inTransform->blueMultiplier, inTransform->alphaMultiplier); + glUniform4f (mColourScaleSlot, inTransform->redMultiplier * rf, inTransform->greenMultiplier * gf, inTransform->blueMultiplier * bf, inTransform->alphaMultiplier * af); } @@ -227,7 +240,7 @@ namespace lime { if (mColourOffsetSlot >= 0) glUniform4f (mColourOffsetSlot, 0, 0, 0, 0); if (mColourScaleSlot >= 0) - glUniform4f (mColourScaleSlot, 1, 1, 1, 1); + glUniform4f (mColourScaleSlot, rf, gf, bf, af); } @@ -257,45 +270,6 @@ namespace lime { } - void OpenGLProgram::setPositionData (const float *inData, bool inIsPerspective) { - - glVertexAttribPointer (mVertexSlot, inIsPerspective ? 4 : 2, GL_FLOAT, GL_FALSE, 0, inData); - glEnableVertexAttribArray (mVertexSlot); - - } - - - void OpenGLProgram::setTexCoordData (const float *inData) { - - if (inData) { - - glVertexAttribPointer (mTexCoordSlot, 2, GL_FLOAT, GL_FALSE, 0, inData); - glEnableVertexAttribArray (mTexCoordSlot); - glUniform1i (mTextureSlot, 0); - - } - - } - - - void OpenGLProgram::setTint (unsigned int inColour) { - - if (mTintSlot >= 0) { - - float a = ((inColour >> 24) & 0xff) * one_on_255; - float c0 = ((inColour >> 16) & 0xff) * one_on_255; - float c1 = ((inColour >> 8) & 0xff) * one_on_255; - float c2 = (inColour & 0xff) * one_on_255; - if (mAlphaMode == amPremultiplied) - glUniform4f (mTintSlot, c0 * a, c1 * a, c2 * a, a); - else - glUniform4f (mTintSlot, c0, c1, c2, a); - - } - - } - - void OpenGLProgram::setTransform (const Trans4x4 &inTrans) { glUniformMatrix4fv (mTransformSlot, 1, 0, inTrans[0]); @@ -304,6 +278,3 @@ namespace lime { } - - -#endif diff --git a/project/src/renderer/opengl/OpenGLShaders.cpp b/project/src/renderer/opengl/OpenGLShaders.cpp index b6146a85d..3ce6a6faa 100644 --- a/project/src/renderer/opengl/OpenGLShaders.cpp +++ b/project/src/renderer/opengl/OpenGLShaders.cpp @@ -5,232 +5,179 @@ namespace lime { - const char *gSolidVert = - "uniform mat4 uTransform;\n" - "attribute vec4 aVertex;\n" - "void main(void)\n" - "{\n" - " gl_Position = aVertex * uTransform;\n" - "}"; - - - const char *gColourVert = - "uniform mat4 uTransform;\n" - "attribute vec4 aVertex;\n" - "attribute vec4 aColourArray;\n" - "varying vec4 vColourArray;\n" - "void main(void)\n" - "{\n" - " vColourArray = aColourArray;\n" - " gl_Position = aVertex * uTransform;\n" - "}"; - - - const char *gTextureVert = - "uniform mat4 uTransform;\n" - "attribute vec4 aVertex;\n" - "attribute vec2 aTexCoord;\n" - "varying vec2 vTexCoord;\n" - "void main(void)\n" - "{\n" - " vTexCoord = aTexCoord;\n" - " gl_Position = aVertex * uTransform;\n" - "}"; - - - const char *gTextureColourVert = - "uniform mat4 uTransform;\n" - "attribute vec4 aColourArray;\n" - "attribute vec4 aVertex;\n" - "attribute vec2 aTexCoord;\n" - "varying vec2 vTexCoord;\n" - "varying vec4 vColourArray;\n" - "void main(void)\n" - "{\n" - " vColourArray = aColourArray;\n" - " vTexCoord = aTexCoord;\n" - " gl_Position = aVertex * uTransform;\n" - "}"; - - - const char *gSolidFrag = - "uniform vec4 uTint;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = uTint;\n" - "}\n"; - - - const char *gColourFrag = - "varying vec4 vColourArray;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = vColourArray;\n" - "}\n"; - - - const char *gColourTransFrag = - "varying vec4 vColourArray;\n" - "uniform vec4 uColourScale;\n" - "uniform vec4 uColourOffset;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = vColourArray*uColourScale+uColourOffset;\n" - "}\n"; - - - const char *gBitmapAlphaFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "uniform vec4 uTint;\n" - "void main(void)\n" - "{\n" - " gl_FragColor.rgb = uTint.rgb;\n" - " gl_FragColor.a = texture2D(uImage0,vTexCoord).a*uTint.a;\n" - "}\n"; - - - const char *gBitmapAlphaPremultFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "uniform vec4 uTint;\n" - "void main(void)\n" - "{\n" - " gl_FragColor.rgb = uTint.rgb*texture2D(uImage0,vTexCoord).a;\n" - " gl_FragColor.a = texture2D(uImage0,vTexCoord).a*uTint.a;\n" - "}\n"; - - - const char *gBitmapFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "uniform vec4 uTint;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = texture2D(uImage0,vTexCoord)*uTint;\n" - "}\n"; - - - const char *gTextureFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = texture2D(uImage0,vTexCoord);\n" - "}\n"; - - - const char *gRadialTextureFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "void main(void)\n" - "{\n" - " float rad = sqrt(vTexCoord.x*vTexCoord.x + vTexCoord.y*vTexCoord.y);\n" - " gl_FragColor = texture2D(uImage0,vec2(rad,0));\n" - "}\n"; - - - const char *gRadialFocusTextureFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "uniform float mA;\n" - "uniform float mFX;\n" - "uniform float mOn2A;\n" - "void main(void)\n" - "{\n" - " float GX = vTexCoord.x - mFX;\n" - " float C = GX*GX + vTexCoord.y*vTexCoord.y;\n" - " float B = 2.0*GX * mFX;\n" - " float det =B*B - mA*C;\n" - " float rad;\n" - " if (det<0.0)\n" - " rad = -B * mOn2A;\n" - " else\n" - " rad = (-B - sqrt(det)) * mOn2A;" - " gl_FragColor = texture2D(uImage0,vec2(rad,0));\n" - "}\n"; - - - const char *gTextureColourFrag = - "uniform sampler2D uImage0;\n" - "varying vec2 vTexCoord;\n" - "varying vec4 vColourArray;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = texture2D(uImage0,vTexCoord) * vColourArray;\n" - "}\n"; - - - const char *gTextureColourPremultFrag = - "uniform sampler2D uImage0;\n" - "varying vec2 vTexCoord;\n" - "varying vec4 vColourArray;\n" - "void main(void)\n" - "{\n" - " gl_FragColor.rgb = texture2D(uImage0,vTexCoord).rgb * vColourArray.rgb * vColourArray.a;\n" - " gl_FragColor.a = texture2D(uImage0,vTexCoord).a * vColourArray.a;\n" - "}\n"; - - - const char *gTextureTransFrag = - "varying vec2 vTexCoord;\n" - "uniform sampler2D uImage0;\n" - "uniform vec4 uColourScale;\n" - "uniform vec4 uColourOffset;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = texture2D(uImage0,vTexCoord) * uColourScale + uColourOffset;\n" - "}\n"; - - - GPUProg *GPUProg::create (GPUProgID inID, AlphaMode inAlphaMode) { + GPUProg *GPUProg::create (unsigned int inID) { - #ifdef ALLOW_OGL2 - switch (inID) { - - case gpuSolid: - return new OpenGLProgram (gSolidVert, gSolidFrag, inAlphaMode); - - case gpuColourTransform: - return new OpenGLProgram (gColourVert, gColourTransFrag, inAlphaMode); - - case gpuColour: - return new OpenGLProgram (gColourVert, gColourFrag, inAlphaMode); - - case gpuRadialGradient: - return new OpenGLProgram (gTextureVert, gRadialTextureFrag, inAlphaMode); - - case gpuRadialFocusGradient: - return new OpenGLProgram (gTextureVert, gRadialFocusTextureFrag, inAlphaMode); - - case gpuTexture: - return new OpenGLProgram (gTextureVert, gTextureFrag, inAlphaMode); - - case gpuTextureColourArray: - if (inAlphaMode == amPremultiplied) - return new OpenGLProgram (gTextureColourVert, gTextureColourPremultFrag, inAlphaMode); - else - return new OpenGLProgram (gTextureColourVert, gTextureColourFrag, inAlphaMode); - - case gpuTextureTransform: - return new OpenGLProgram (gTextureVert, gTextureTransFrag, inAlphaMode); - - case gpuBitmap: - return new OpenGLProgram (gTextureVert, gBitmapFrag, inAlphaMode); - - case gpuBitmapAlpha: - if (inAlphaMode == amPremultiplied) - return new OpenGLProgram (gTextureVert, gBitmapAlphaPremultFrag, inAlphaMode); - else - return new OpenGLProgram (gTextureVert, gBitmapAlphaFrag, inAlphaMode); - - default: - break; - - } + std::string vertexVars = + "uniform mat4 uTransform;\n" + "attribute vec4 aVertex;\n"; + + std::string vertexProg = + " gl_Position = aVertex * uTransform;\n"; + + std::string pixelVars = ""; + std::string pixelProlog = ""; + + #ifdef LIME_GLES + pixelVars = std::string ("precision mediump float;\n"); #endif - return 0; + std::string fragColour = ""; + + if (inID & PROG_TINT) { + + pixelVars += "uniform vec4 uColourScale;\n"; + fragColour = "uColourScale"; + + } + + if (inID & PROG_COLOUR_OFFSET) { + + pixelVars += "uniform vec4 uColourOffset;\n"; + + } + + if (inID & PROG_COLOUR_PER_VERTEX) { + + vertexVars += + "attribute vec4 aColourArray;\n" + "varying vec4 vColourArray;\n"; + + vertexProg = + " vColourArray = aColourArray;\n" + vertexProg; + + pixelVars += + "varying vec4 vColourArray;\n"; + + if (fragColour != "") { + + fragColour += "*"; + + } + + fragColour += "vColourArray"; + + } + + if (inID & PROG_TEXTURE) { + + vertexVars += + "attribute vec2 aTexCoord;\n" + "varying vec2 vTexCoord;\n"; + + vertexProg = + " vTexCoord = aTexCoord;\n" + vertexProg; + + pixelVars += + "uniform sampler2D uImage0;\n" + "varying vec2 vTexCoord;\n"; + + if (!(inID & PROG_RADIAL)) { + + if (fragColour != "") { + + fragColour += "*"; + + } + + if (inID & PROG_ALPHA_TEXTURE) { + + fragColour += "vec4(1,1,1,texture2D(uImage0,vTexCoord).a)"; + + } else { + + fragColour += "texture2D(uImage0,vTexCoord)"; + + } + + } + + } + + if (inID & PROG_RADIAL) { + + if (inID & PROG_RADIAL_FOCUS) { + + pixelVars += + "uniform float mA;\n" + "uniform float mFX;\n" + "uniform float mOn2A;\n"; + + pixelProlog = + " float GX = vTexCoord.x - mFX;\n" + " float C = GX*GX + vTexCoord.y*vTexCoord.y;\n" + " float B = 2.0*GX * mFX;\n" + " float det =B*B - mA*C;\n" + " float rad;\n" + " if (det<0.0)\n" + " rad = -B * mOn2A;\n" + " else\n" + " rad = (-B - sqrt(det)) * mOn2A;\n"; + + } else { + + pixelProlog = + " float rad = sqrt(vTexCoord.x*vTexCoord.x + vTexCoord.y*vTexCoord.y);\n"; + + } + + if (fragColour != "") { + + fragColour += "*"; + + } + + fragColour += "texture2D(uImage0,vec2(rad,0))"; + + } + + if (inID & PROG_NORMAL_DATA) { + + vertexVars += + "attribute vec2 aNormal;\n" + "varying vec2 vNormal;\n"; + + vertexProg = + " vNormal = aNormal;\n" + vertexProg; + + pixelVars += + "varying vec2 vNormal;\n"; + + } + + std::string vertexShader = + vertexVars + + "void main()\n" + "{\n" + + vertexProg + + "}\n"; + + if (fragColour == "") { + + fragColour = "vec4(1,1,1,1)"; + + } + + if (inID & PROG_COLOUR_OFFSET) { + + fragColour = fragColour + "+ uColourOffset"; + + } + + if (inID & PROG_NORMAL_DATA) { + + fragColour = "(" + fragColour + ") * vec4(1,1,1, min(vNormal.x-abs(vNormal.y),1.0) )"; + + } + + std::string pixelShader = + pixelVars + + "void main()\n" + "{\n" + + pixelProlog + + " gl_FragColor = " + fragColour + ";\n" + + "}\n"; + + return new OpenGLProgram (vertexShader, pixelShader); }