diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-12-22 21:39:39 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-12-22 21:39:39 +0000 |
commit | ac10a2d039c5d52eed66e27cbbc503ab523c1cd5 (patch) | |
tree | c5be0c3dd15052016e7d32f376507cb1ea7101dd /gpu/include | |
parent | ea8509cd3b1771b36054313d3ccd56679df56044 (diff) |
add gpu backend (not hooked up yet)
git-svn-id: http://skia.googlecode.com/svn/trunk@649 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu/include')
60 files changed, 8805 insertions, 0 deletions
diff --git a/gpu/include/FlingState.h b/gpu/include/FlingState.h new file mode 100644 index 0000000000..a1da4fbc86 --- /dev/null +++ b/gpu/include/FlingState.h @@ -0,0 +1,59 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkFlingState_DEFINED +#define SkFlingState_DEFINED + +#include "SkScalar.h" +#include "SkPoint.h" + +class SkMatrix; + +struct FlingState { + FlingState() : fActive(false) {} + + bool isActive() const { return fActive; } + void stop() { fActive = false; } + + void reset(float sx, float sy); + bool evaluateMatrix(SkMatrix* matrix); + +private: + SkPoint fDirection; + SkScalar fSpeed0; + double fTime0; + bool fActive; +}; + +class GrAnimateFloat { +public: + GrAnimateFloat(); + + void start(float v0, float v1, float duration); + bool isActive() const { return fTime0 != 0; } + void stop() { fTime0 = 0; } + + float evaluate(); + +private: + float fValue0, fValue1, fDuration; + SkMSec fTime0; +}; + +#endif + + diff --git a/gpu/include/GrAPI.h b/gpu/include/GrAPI.h new file mode 100644 index 0000000000..b660e8d869 --- /dev/null +++ b/gpu/include/GrAPI.h @@ -0,0 +1,37 @@ + + +class GrAPI { +public: + + void setRenderTarget(GrRenderTarget* target); + + void setMatrix(const GrMatrix&); + + void setClip(rect, bool aa); + void setClip(rect[], bool aa); + void setClip(path, bool aa); + void setClip(rect, texture/key, state, matrix); + void setClip(path, texture/key, state, matrix); + + void setColor(color); + void setTexture(texture/key, sampler, const GrMatrix* = NULL); + void setBlend(src, dst); + + void drawRect(const GrRect&, stroke, join); + void drawOval(const GrRect&, stroke); + void drawRoundRect(const GrRect&, GrScalar ovalW, GrScalar ovalH, stroke); + void drawPath(const GrPathIter&, GrPathFill); + void drawVertices(...); + void drawGlyphs(const uint16_t[], int count, const GrPoint[], GrFontScaler*); + +/// + + void save(); + void restore(); + void concatMatrix(const GrMatrix&); + void concatClipRect(const GrRect&); + void concatClipPath(const GrPathIter&, bool aa); + +}; + + diff --git a/gpu/include/GrAllocPool.h b/gpu/include/GrAllocPool.h new file mode 100644 index 0000000000..46359e5058 --- /dev/null +++ b/gpu/include/GrAllocPool.h @@ -0,0 +1,71 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrAllocPool_DEFINED +#define GrAllocPool_DEFINED + +#include "GrNoncopyable.h" + +class GrAllocPool : GrNoncopyable { +public: + GrAllocPool(size_t blockSize = 0); + ~GrAllocPool(); + + /** + * Frees all blocks that have been allocated with alloc(). + */ + void reset(); + + /** + * Returns a block of memory bytes size big. This address must not be + * passed to realloc/free/delete or any other function that assumes the + * address was allocated by malloc or new (becuase it hasn't). + */ + void* alloc(size_t bytes); + + /** + * Releases the most recently allocated bytes back to allocpool. + */ + void release(size_t bytes); + +private: + struct Block; + + Block* fBlock; + size_t fMinBlockSize; + +#if GR_DEBUG + int fBlocksAllocated; + void validate() const; +#else + void validate() const {} +#endif +}; + +template <typename T> class GrTAllocPool { +public: + GrTAllocPool(int count) : fPool(count * sizeof(T)) {} + + void reset() { fPool.reset(); } + T* alloc() { return (T*)fPool.alloc(sizeof(T)); } + +private: + GrAllocPool fPool; +}; + +#endif + diff --git a/gpu/include/GrAllocator.h b/gpu/include/GrAllocator.h new file mode 100755 index 0000000000..da02ba40b0 --- /dev/null +++ b/gpu/include/GrAllocator.h @@ -0,0 +1,230 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrAllocator_DEFINED +#define GrAllocator_DEFINED + +#include "GrConfig.h" +#include "GrTArray.h" + +class GrAllocator { +public: + virtual ~GrAllocator() { + reset(); + } + + /** + * Create an allocator + * + * @param itemSize the size of each item to allocate + * @param itemsPerBlock the number of items to allocate at once + * @param initialBlock optional memory to use for the first block. + * Must be at least itemSize*itemsPerBlock sized. + * Caller is responsible for freeing this memory. + */ + GrAllocator(size_t itemSize, uint32_t itemsPerBlock, void* initialBlock) : + fBlocks(fBlockInitialStorage, NUM_INIT_BLOCK_PTRS), + fItemSize(itemSize), + fItemsPerBlock(itemsPerBlock), + fOwnFirstBlock(NULL == initialBlock), + fCount(0) { + fBlockSize = fItemSize * fItemsPerBlock; + fBlocks.push_back() = initialBlock; + GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} ); + } + + /** + * Adds an item and returns pointer to it. + * + * @return pointer to the added item. + */ + void* push_back() { + uint32_t indexInBlock = fCount % fItemsPerBlock; + // we always have at least one block + if (0 == indexInBlock) { + if (0 != fCount) { + fBlocks.push_back() = GrMalloc(fBlockSize); + } else if (fOwnFirstBlock) { + fBlocks[0] = GrMalloc(fBlockSize); + } + } + void* ret = (char*)fBlocks[fCount/fItemsPerBlock] + + fItemSize * indexInBlock; + ++fCount; + return ret; + } + + /** + * removes all added items + */ + void reset() { + uint32_t blockCount = GrMax((unsigned)1, + GrUIDivRoundUp(fCount, fItemsPerBlock)); + for (uint32_t i = 1; i < blockCount; ++i) { + GrFree(fBlocks[i]); + } + if (fOwnFirstBlock) { + GrFree(fBlocks[0]); + fBlocks[0] = NULL; + } + fBlocks.pop_back_n(blockCount-1); + fCount = 0; + } + + /** + * count of items + */ + uint32_t count() const { + return fCount; + } + + /** + * is the count 0 + */ + bool empty() const { return fCount == 0; } + + /** + * access last item, only call if count() != 0 + */ + void* back() { + GrAssert(fCount); + return (*this)[fCount-1]; + } + + /** + * access last item, only call if count() != 0 + */ + const void* back() const { + GrAssert(fCount); + return (*this)[fCount-1]; + } + + /** + * access item by index. + */ + void* operator[] (uint32_t i) { + GrAssert(i < fCount); + return (char*)fBlocks[i / fItemsPerBlock] + + fItemSize * (i % fItemsPerBlock); + } + + /** + * access item by index. + */ + const void* operator[] (uint32_t i) const { + GrAssert(i < fCount); + return (const char*)fBlocks[i / fItemsPerBlock] + + fItemSize * (i % fItemsPerBlock); + } + +private: + static const uint32_t NUM_INIT_BLOCK_PTRS = 8; + + GrTArray<void*> fBlocks; + size_t fBlockSize; + char fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)]; + size_t fItemSize; + uint32_t fItemsPerBlock; + bool fOwnFirstBlock; + uint32_t fCount; +}; + +template <typename T> +class GrTAllocator { +private: + GrAllocator fAllocator; + +public: + virtual ~GrTAllocator() {}; + + /** + * Create an allocator + * + * @param itemsPerBlock the number of items to allocate at once + * @param initialBlock optional memory to use for the first block. + * Must be at least size(T)*itemsPerBlock sized. + * Caller is responsible for freeing this memory. + */ + GrTAllocator(uint32_t itemsPerBlock, void* initialBlock) : + fAllocator(sizeof(T), itemsPerBlock, initialBlock) + {} + + /** + * Adds an item and returns it. + * + * @return the added item. + */ + T& push_back() { + void* item = fAllocator.push_back(); + GrAssert(NULL != item); + new (item) T; + return *(T*)item; + } + + /** + * removes all added items + */ + void reset() { + uint32_t c = fAllocator.count(); + for (uint32_t i = 0; i < c; ++i) { + ((T*)fAllocator[i])->~T(); + } + fAllocator.reset(); + } + + /** + * count of items + */ + uint32_t count() const { + return fAllocator.count(); + } + + /** + * is the count 0 + */ + bool empty() const { return fAllocator.empty(); } + + /** + * access last item, only call if count() != 0 + */ + T& back() { + return *(T*)fAllocator.back(); + } + + /** + * access last item, only call if count() != 0 + */ + const T& back() const { + return *(const T*)fAllocator.back(); + } + + /** + * access item by index. + */ + T& operator[] (uint32_t i) { + return *(T*)(fAllocator[i]); + } + + /** + * access item by index. + */ + const T& operator[] (uint32_t i) const { + return *(const T*)(fAllocator[i]); + } +}; + +#endif diff --git a/gpu/include/GrAtlas.h b/gpu/include/GrAtlas.h new file mode 100644 index 0000000000..9526e0bb4c --- /dev/null +++ b/gpu/include/GrAtlas.h @@ -0,0 +1,88 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrAtlas_DEFINED +#define GrAtlas_DEFINED + +#include "GrPoint.h" +#include "GrTexture.h" +#include "GrTDArray.h" + +class GrGpu; +class GrRectanizer; +class GrAtlasMgr; + +class GrAtlas { +public: + GrAtlas(GrAtlasMgr*, int plotX, int plotY); + + int getPlotX() const { return fPlot.fX; } + int getPlotY() const { return fPlot.fY; } + + GrTexture* texture() const { return fTexture; } + + bool addSubImage(int width, int height, const void*, GrIPoint16*); + + static void FreeLList(GrAtlas* atlas) { + while (atlas) { + GrAtlas* next = atlas->fNext; + delete atlas; + atlas = next; + } + } + + // testing + GrAtlas* nextAtlas() const { return fNext; } + +private: + ~GrAtlas(); // does not try to delete the fNext field + + GrAtlas* fNext; + GrTexture* fTexture; + GrRectanizer* fRects; + GrAtlasMgr* fAtlasMgr; + GrIPoint16 fPlot; + + friend class GrAtlasMgr; +}; + +class GrPlotMgr; + +class GrAtlasMgr { +public: + GrAtlasMgr(GrGpu*); + ~GrAtlasMgr(); + + GrAtlas* addToAtlas(GrAtlas*, int width, int height, const void*, + GrIPoint16*); + + GrTexture* getTexture() const { return fTexture; } + + // to be called by ~GrAtlas() + void freePlot(int x, int y); + + void abandonAll(); + +private: + GrGpu* fGpu; + GrTexture* fTexture; + GrPlotMgr* fPlotMgr; +}; + +#endif + + diff --git a/gpu/include/GrClip.h b/gpu/include/GrClip.h new file mode 100644 index 0000000000..8e3030c753 --- /dev/null +++ b/gpu/include/GrClip.h @@ -0,0 +1,115 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrClip_DEFINED +#define GrClip_DEFINED + +#include "GrClipIterator.h" +#include "GrRect.h" +#include "GrTDArray.h" + +class GrClip { +public: + GrClip(); + GrClip(const GrClip& src); + GrClip(GrClipIterator* iter); + ~GrClip(); + + GrClip& operator=(const GrClip& src); + + bool isEmpty() const { return fBounds.isEmpty(); } + bool isComplex() const { return fList.count() > 0; } + bool isRect() const { + return !this->isEmpty() && !this->isComplex(); + } + + const GrIRect& getBounds() const { return fBounds; } + + /** + * Resets this clip to be empty (fBounds is empty, and fList is empty) + */ + void setEmpty(); + + /** + * Resets this clip to have fBounds == rect, and fList is empty. + */ + void setRect(const GrIRect& rect); + + /** + * Append a rect to an existing clip. The call must ensure that rect does + * not overlap with any previous rect in this clip (either from setRect + * or addRect). fBounds is automatically updated to reflect the union of + * all rects that have been added. + */ + void addRect(const GrIRect&); + + void setFromIterator(GrClipIterator* iter); + + friend bool operator==(const GrClip& a, const GrClip& b) { + return a.fBounds == b.fBounds && a.fList == b.fList; + } + friend bool operator!=(const GrClip& a, const GrClip& b) { + return !(a == b); + } + + /** + * Return the number of rects in this clip: 0 for empty, 1 for a rect, + * or N for a complex clip. + */ + int countRects() const { + return this->isEmpty() ? 0 : GrMax<int>(1, fList.count()); + } + + /** + * Return an array of rects for this clip. Use countRects() to know the + * number of entries. + */ + const GrIRect* getRects() const { + return fList.count() > 0 ? fList.begin() : &fBounds; + } + +#if GR_DEBUG + void validate() const; +#else + void validate() const {} +#endif + +private: + GrTDArray<GrIRect> fList; + GrIRect fBounds; +}; + +class GrClipIter : public GrClipIterator { +public: + GrClipIter(const GrClip& clip) : fClip(&clip), fIndex(0) {} + GrClipIter() : fClip(NULL), fIndex(0) {} + + void reset(const GrClip& clip); + + virtual bool isDone(); + virtual void rewind(); + virtual void getRect(GrIRect* r); + virtual void next(); + virtual void computeBounds(GrIRect* r); + +private: + const GrClip* fClip; + int fIndex; +}; + +#endif + diff --git a/gpu/include/GrClipIterator.h b/gpu/include/GrClipIterator.h new file mode 100644 index 0000000000..d1fe4dde2f --- /dev/null +++ b/gpu/include/GrClipIterator.h @@ -0,0 +1,81 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrClipIterator_DEFINED +#define GrClipIterator_DEFINED + +#include "GrRect.h" + +class GrClipIterator { +public: + GrClipIterator() : fNeedBounds(true) {} + virtual ~GrClipIterator() {} + + /** + * Returns true if there are no more rects to process + */ + virtual bool isDone() = 0; + + /** + * Rewind the iterate to replay the set of rects again + */ + virtual void rewind() = 0; + + /** + * Return the current rect. It is an error to call this when done() is true + */ + virtual void getRect(GrIRect*) = 0; + + /** + * Call to move to the next rect in the set + */ + virtual void next() = 0; + + /** + * Set bounds to be the bounds of the clip. + */ + virtual void computeBounds(GrIRect* bounds) = 0; + + /** + * Subclass should call this whenever their underlying bounds has changed. + */ + void invalidateBoundsCache() { fNeedBounds = true; } + + const GrIRect& getBounds() { + if (fNeedBounds) { + this->computeBounds(&fBounds); + fNeedBounds = false; + } + return fBounds; + } + +private: + GrIRect fBounds; + bool fNeedBounds; +}; + +/** + * Call to rewind iter, first checking to see if iter is NULL + */ +static inline void GrSafeRewind(GrClipIterator* iter) { + if (iter) { + iter->rewind(); + } +} + +#endif + diff --git a/gpu/include/GrColor.h b/gpu/include/GrColor.h new file mode 100644 index 0000000000..8dc03d258c --- /dev/null +++ b/gpu/include/GrColor.h @@ -0,0 +1,72 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrColor_DEFINED +#define GrColor_DEFINED + +#include "GrTypes.h" + +/** + * GrColor is 4 bytes for R, G, B, A, in a compile-time specific order. The + * components are stored premultiplied. + */ +typedef uint32_t GrColor; + +// indices for address a GrColor as an array of bytes + +#define GrColor_INDEX_R 0 +#define GrColor_INDEX_G 1 +#define GrColor_INDEX_B 2 +#define GrColor_INDEX_A 3 + +// shfit amount to assign a component to a GrColor int + +#define GrColor_SHIFT_R 0 +#define GrColor_SHIFT_G 8 +#define GrColor_SHIFT_B 16 +#define GrColor_SHIFT_A 24 + +/** + * Pack 4 components (RGBA) into a GrColor int + */ +static inline GrColor GrColorPackRGBA(unsigned r, unsigned g, + unsigned b, unsigned a) { + GrAssert((uint8_t)r == r); + GrAssert((uint8_t)g == g); + GrAssert((uint8_t)b == b); + GrAssert((uint8_t)a == a); + return (r << GrColor_SHIFT_R) | + (g << GrColor_SHIFT_G) | + (b << GrColor_SHIFT_B) | + (a << GrColor_SHIFT_A); +} + +// extract a component (byte) from a GrColor int + +#define GrColorUnpackR(color) (((color) >> GrColor_SHIFT_R) & 0xFF) +#define GrColorUnpackG(color) (((color) >> GrColor_SHIFT_G) & 0xFF) +#define GrColorUnpackB(color) (((color) >> GrColor_SHIFT_B) & 0xFF) +#define GrColorUnpackA(color) (((color) >> GrColor_SHIFT_A) & 0xFF) + +/** + * Since premultiplied means that alpha >= color, we construct a color with + * each component==255 and alpha == 0 to be "illegal" + */ +#define GrColor_ILLEGAL (~(0xFF << GrColor_SHIFT_A)) + +#endif + diff --git a/gpu/include/GrConfig.h b/gpu/include/GrConfig.h new file mode 100644 index 0000000000..9c18f60ef6 --- /dev/null +++ b/gpu/include/GrConfig.h @@ -0,0 +1,344 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrConfig_DEFINED +#define GrConfig_DEFINED + +/////////////////////////////////////////////////////////////////////////////// +// preconfig section: +// +// All the work before including GrUserConfig.h should center around guessing +// what platform we're on, and defining low-level symbols based on that. +// +// A build environment may have already defined symbols, so we first check +// for that +// + +// hack to ensure we know what sort of Apple platform we're on +#if defined(__APPLE_CPP__) || defined(__APPLE_CC__) + #include <TargetConditionals.h> +#endif + +/** + * Gr defines are set to 0 or 1, rather than being undefined or defined + */ + +#if !defined(GR_ANDROID_BUILD) + #define GR_ANDROID_BUILD 0 +#endif +#if !defined(GR_IOS_BUILD) + #define GR_IOS_BUILD 0 +#endif +#if !defined(GR_LINUX_BUILD) + #define GR_LINUX_BUILD 0 +#endif +#if !defined(GR_MAC_BUILD) + #define GR_MAC_BUILD 0 +#endif +#if !defined(GR_WIN32_BUILD) + #define GR_WIN32_BUILD 0 +#endif +#if !defined(GR_QNX_BUILD) + #define GR_QNX_BUILD 0 +#endif + +/** + * If no build target has been defined, attempt to infer. + */ +#if !GR_ANDROID_BUILD && !GR_IOS_BUILD && !GR_LINUX_BUILD && !GR_MAC_BUILD && !GR_WIN32_BUILD && !GR_QNX_BUILD + #if defined(_WIN32) + #undef GR_WIN32_BUILD + #define GR_WIN32_BUILD 1 +// #error "WIN" + #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + #undef GR_IOS_BUILD + #define GR_IOS_BUILD 1 +// #error "IOS" + #elif ANDROID_NDK || defined(ANDROID) + #undef GR_ANDROID_BUILD + #define GR_ANDROID_BUILD 1 +// #error "ANDROID" + #elif TARGET_OS_MAC + #undef GR_MAC_BUILD + #define GR_MAC_BUILD 1 +// #error "MAC" + #elif TARGET_OS_QNX || defined(__QNXNTO__) + #undef GR_QNX_BUILD + #define GR_QNX_BUILD 1 +// #error "QNX" + #else + #undef GR_LINUX_BUILD + #define GR_LINUX_BUILD 1 +// #error "LINUX" + #endif +#endif + +#if !defined(GR_DEBUG) && !defined(GR_RELEASE) + #ifdef NDEBUG + #define GR_DEBUG 0 + #else + #define GR_DEBUG 1 + #endif + #define GR_RELEASE !GR_DEBUG +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/* + * Pull stdint.h in before user-config, to be sure our __STDC... macros are + * defined before anyone else might try to include stdint.h + */ +#define __STDC_LIMIT_MACROS +#define __STDC_CONSTANT_MACROS +#include <stdint.h> + +/* + * The "user config" file can be empty, and everything should work. It is + * meant to store a given platform/client's overrides of our guess-work. + * + * A alternate user config file can be specified by defining + * GR_USER_CONFIG_FILE. It should be defined relative to GrConfig.h + * + * e.g. it can specify GR_DEBUG/GR_RELEASE as it please, change the BUILD + * target, or supply its own defines for anything else (e.g. GR_SCALAR) + */ +#if !defined(GR_USER_CONFIG_FILE) + #include "GrUserConfig.h" +#else + #include GR_USER_CONFIG_FILE +#endif + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// postconfig section: +// +// By now we must have a GR_..._BUILD symbol set to 1, and a decision about +// debug -vs- release +// + +extern void GrPrintf(const char format[], ...); + +/** + * GR_STRING makes a string of X where X is expanded before conversion to a string + * if X itself contains macros. + */ +#define GR_STRING(X) GR_STRING_IMPL(X) +#define GR_STRING_IMPL(X) #X + +/** + * GR_CONCAT concatenates X and Y where each is expanded before + * contanenation if either contains macros. + */ +#define GR_CONCAT(X,Y) GR_CONCAT_IMPL(X,Y) +#define GR_CONCAT_IMPL(X,Y) X##Y + +/** + * Creates a string of the form "<filename>(<linenumber>) : " + */ +#define GR_FILE_AND_LINE_STR __FILE__ "(" GR_STRING(__LINE__) ") : " + +/** + * Compilers have different ways of issuing warnings. This macro + * attempts to abstract them, but may need to be specialized for your + * particular compiler. + * To insert compiler warnings use "#pragma message GR_WARN(<string>)" + */ +#if _MSC_VER + #define GR_WARN(MSG) (GR_FILE_AND_LINE_STR "WARNING: " MSG) +#else//__GNUC__ - may need other defines for different compilers + #define GR_WARN(MSG) ("WARNING: " MSG) +#endif + +/** + * GR_ALWAYSBREAK is an unconditional break in all builds. + */ +#if !defined(GR_ALWAYSBREAK) + #if GR_WIN32_BUILD + #define GR_ALWAYSBREAK __debugbreak() + #else + // TODO: do other platforms really not have continuable breakpoints? + // sign extend for 64bit architectures to be sure this is + // in the high address range + #define GR_ALWAYSBREAK *((int*)(int64_t)(int32_t)0xbeefcafe) = 0; + #endif +#endif + +/** + * GR_DEBUGBREAK is an unconditional break in debug builds. + */ +#if !defined(GR_DEBUGBREAK) + #if GR_DEBUG + #define GR_DEBUGBREAK GR_ALWAYSBREAK + #else + #define GR_DEBUGBREAK + #endif +#endif + +/** + * GR_ALWAYSASSERT is an assertion in all builds. + */ +#if !defined(GR_ALWAYSASSERT) + #define GR_ALWAYSASSERT(COND) \ + do { \ + if (!(COND)) { \ + GrPrintf("%s %s failed\n", GR_FILE_AND_LINE_STR, #COND); \ + GR_ALWAYSBREAK; \ + } \ + } while (false) +#endif + +/** + * GR_DEBUGASSERT is an assertion in debug builds only. + */ +#if !defined(GR_DEBUGASSERT) + #if GR_DEBUG + #define GR_DEBUGASSERT(COND) GR_ALWAYSASSERT(COND) + #else + #define GR_DEBUGASSERT(COND) + #endif +#endif + +/** + * Prettier forms of the above macros. + */ +#define GrAssert(COND) GR_DEBUGASSERT(COND) +#define GrAlwaysAssert(COND) GR_ALWAYSASSERT(COND) + +/** + * GR_DEBUGCODE compiles the code X in debug builds only + */ +#if !defined(GR_DEBUGCODE) + #if GR_DEBUG + #define GR_DEBUGCODE(X) X + #else + #define GR_DEBUGCODE(X) + #endif +#endif + +/** + * GR_STATIC_ASSERT is a compile time assertion. Depending on the platform + * it may print the message in the compiler log. Obviously, the condition must + * be evaluatable at compile time. + */ +// VS 2010 and GCC compiled with c++0x or gnu++0x support the new +// static_assert. +#if !defined(GR_STATIC_ASSERT) + #if (_MSC_VER >= 1600) || __GXX_EXPERIMENTAL_CXX0X__ + #define GR_STATIC_ASSERT(CONDITION) static_assert(CONDITION, "bug") + #else + template <bool> class GR_STATIC_ASSERT_FAILURE; + template <> class GR_STATIC_ASSERT_FAILURE<true> {}; + #define GR_STATIC_ASSERT(CONDITION) \ + enum {GR_CONCAT(X,__LINE__) = \ + sizeof(GR_STATIC_ASSERT_FAILURE<CONDITION>)} + #endif +#endif + +#if !defined(GR_SCALAR_IS_FLOAT) + #define GR_SCALAR_IS_FLOAT 0 +#endif +#if !defined(GR_SCALAR_IS_FIXED) + #define GR_SCALAR_IS_FIXED 0 +#endif + +#if !defined(GR_TEXT_SCALAR_TYPE_IS_USHORT) + #define GR_TEXT_SCALAR_TYPE_IS_USHORT 0 +#endif +#if !defined(GR_TEXT_SCALAR_TYPE_IS_FLOAT) + #define GR_TEXT_SCALAR_TYPE_IS_FLOAT 0 +#endif +#if !defined(GR_TEXT_SCALAR_TYPE_IS_FIXED) + #define GR_TEXT_SCALAR_TYPE_IS_FIXED 0 +#endif + +#ifndef GR_DUMP_TEXTURE_UPLOAD + #define GR_DUMP_TEXTURE_UPLOAD 0 +#endif + +/** + * GR_COLLECT_STATS controls whether the GrGpu class collects stats. + * If not already defined then collect in debug build but not release. + */ +#if !defined(GR_COLLECT_STATS) + #define GR_COLLECT_STATS GR_DEBUG +#endif + +/** + * GR_GL_LOG_CALLS controls whether each GL call is logged. + */ +#if !defined(GR_GL_LOG_CALLS) + #define GR_GL_LOG_CALLS 0 +#endif + +/////////////////////////////////////////////////////////////////////////////// +// tail section: +// +// Now we just assert if we are missing some required define, or if we detect +// and inconsistent combination of defines +// + + +/** + * Only one build target macro should be 1 and the rest should be 0. + */ +#define GR_BUILD_SUM (GR_WIN32_BUILD + GR_MAC_BUILD + GR_IOS_BUILD + GR_ANDROID_BUILD + GR_LINUX_BUILD + GR_QNX_BUILD) +#if 0 == GR_BUILD_SUM + #error "Missing a GR_BUILD define" +#elif 1 != GR_BUILD_SUM + #error "More than one GR_BUILD defined" +#endif + + +#if !GR_SCALAR_IS_FLOAT && !GR_SCALAR_IS_FIXED + #undef GR_SCALAR_IS_FLOAT + #define GR_SCALAR_IS_FLOAT 1 + #pragma message GR_WARN("Scalar type not defined, defaulting to float") +#endif + +#if !GR_TEXT_SCALAR_IS_FLOAT && \ + !GR_TEXT_SCALAR_IS_FIXED && \ + !GR_TEXT_SCALAR_IS_USHORT + #undef GR_TEXT_SCALAR_IS_FLOAT + #define GR_TEXT_SCALAR_IS_FLOAT 1 + #pragma message GR_WARN("Text scalar type not defined, defaulting to float") +#endif + +#if 0 +#if GR_WIN32_BUILD +// #pragma message GR_WARN("GR_WIN32_BUILD") +#endif +#if GR_MAC_BUILD +// #pragma message GR_WARN("GR_MAC_BUILD") +#endif +#if GR_IOS_BUILD +// #pragma message GR_WARN("GR_IOS_BUILD") +#endif +#if GR_ANDROID_BUILD +// #pragma message GR_WARN("GR_ANDROID_BUILD") +#endif +#if GR_LINUX_BUILD +// #pragma message GR_WARN("GR_LINUX_BUILD") +#endif +#if GR_QNX_BUILD +// #pragma message GR_WARN("GR_QNX_BUILD") +#endif +#endif + +#endif + diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h new file mode 100644 index 0000000000..f9d5ed5090 --- /dev/null +++ b/gpu/include/GrContext.h @@ -0,0 +1,322 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrContext_DEFINED
+#define GrContext_DEFINED
+
+#include "GrClip.h"
+#include "GrGpu.h"
+#include "GrSamplerState.h"
+#include "GrTextureCache.h"
+#include "GrInOrderDrawBuffer.h"
+#include "GrVertexBufferAllocPool.h"
+
+class GrFontCache;
+class GrPathIter;
+
+//TODO: move GrGpu enums/nested types here
+
+class GrContext : public GrRefCnt {
+public:
+ /**
+ * Creates a GrContext from within a 3D context.
+ */
+ static GrContext* Create(GrGpu::Engine engine,
+ GrGpu::Platform3DContext context3D);
+
+ virtual ~GrContext();
+
+ /**
+ * The GrContext normally assumes that no outsider is setting state
+ * within the underlying 3D API's context/device/whatever. This call informs
+ * the context that the state was modified and it should resend. Shouldn't
+ * be called frequently for good performance.
+ */
+ void resetContext();
+
+ /**
+ * Abandons all textures. Call this if you have lost the associated GPU
+ * context, and thus internal texture references/IDs are now invalid.
+ */
+ void abandonAllTextures();
+
+ /**
+ * Search for an entry with the same Key. If found, "lock" it and return it.
+ * If not found, return null.
+ */
+ GrTextureEntry* findAndLockTexture(GrTextureKey*,
+ const GrSamplerState&);
+
+
+ /**
+ * Create a new entry, based on the specified key and texture, and return
+ * its "locked" entry.
+ *
+ * Ownership of the texture is transferred to the Entry, which will unref()
+ * it when we are purged or deleted.
+ */
+ GrTextureEntry* createAndLockTexture(GrTextureKey* key,
+ const GrSamplerState&,
+ const GrGpu::TextureDesc&,
+ void* srcData, size_t rowBytes);
+
+ /**
+ * When done with an entry, call unlockTexture(entry) on it, which returns
+ * it to the cache, where it may be purged.
+ */
+ void unlockTexture(GrTextureEntry* entry);
+
+ /**
+ * Removes an texture from the cache. This prevents the texture from
+ * being found by a subsequent findAndLockTexture() until it is
+ * reattached. The entry still counts against the cache's budget and should
+ * be reattached when exclusive access is no longer needed.
+ */
+ void detachCachedTexture(GrTextureEntry*);
+
+ /**
+ * Reattaches a texture to the cache and unlocks it. Allows it to be found
+ * by a subsequent findAndLock or be purged (provided its lock count is
+ * now 0.)
+ */
+ void reattachAndUnlockCachedTexture(GrTextureEntry*);
+
+ /**
+ * Creates a texture that is outside the cache. Does not count against
+ * cache's budget.
+ */
+ GrTexture* createUncachedTexture(const GrGpu::TextureDesc&,
+ void* srcData,
+ size_t rowBytes);
+
+ /**
+ * Wraps an externally-created rendertarget in a GrRenderTarget.
+ * e.g. in GL platforamRenderTarget is an FBO id.
+ */
+ GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
+ int width, int height);
+
+ /**
+ * Returns true if the specified use of an indexed texture is supported.
+ */
+ bool supportsIndex8PixelConfig(const GrSamplerState&, int width, int height);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ GrRenderTarget* currentRenderTarget() const;
+ void getViewMatrix(GrMatrix* m) const;
+ const GrClip& getClip() const { return fGpu->getClip(); }
+
+ void setRenderTarget(GrRenderTarget* target);
+ void setDefaultRenderTargetSize(uint32_t width, uint32_t height);
+ GrRenderTarget* defaultRenderTarget() { return fGpu->defaultRenderTarget(); }
+
+ void setTexture(GrTexture* texture);
+ void setSamplerState(const GrSamplerState&);
+ void setTextureMatrix(const GrMatrix& m);
+
+ void setAntiAlias(bool);
+ void setDither(bool);
+ void setAlpha(uint8_t alpha);
+ void setColor(GrColor color);
+ void setPointSize(float size);
+ void setBlendFunc(GrGpu::BlendCoeff srcCoef, GrGpu::BlendCoeff dstCoef);
+ void setViewMatrix(const GrMatrix& m);
+ void setClip(const GrClip&);
+
+ /**
+ * Erase the entire render target, ignoring any clips/scissors.
+ */
+ void eraseColor(GrColor color);
+
+ /**
+ * Draw everywhere (respecting the clip) with the current color.
+ */
+ void drawFull(bool useTexture);
+
+ /**
+ * Draw the rect, respecting the current texture if useTexture is true.
+ * If strokeWidth < 0, then the rect is filled, else the rect is stroked
+ * based on strokeWidth. If strokeWidth == 0, then the stroke is always
+ * a single pixel thick.
+ */
+ void drawRect(const GrRect&, bool useTexture, GrScalar strokeWidth);
+
+ void fillRect(const GrRect& rect, bool useTexture) {
+ this->drawRect(rect, useTexture, -1);
+ }
+
+ /**
+ * Path filling rules
+ */
+ enum PathFills {
+ kWinding_PathFill,
+ kEvenOdd_PathFill,
+ kInverseWinding_PathFill,
+ kInverseEvenOdd_PathFill,
+ kHairLine_PathFill,
+
+ kPathFillCount
+ };
+
+ /**
+ * Tessellates and draws a path.
+ *
+ * @param path the path to draw
+ * @param paint the paint to set before drawing
+ * @param useTexture if true the path vertices will also be used as
+ * texture coorindates referencing last texture passed
+ * to setTexture.
+ */
+ void drawPath(GrPathIter* path,
+ PathFills fill,
+ bool useTexture,
+ const GrPoint* translate = NULL);
+
+ /**
+ * Call to ensure all drawing to the context has been issued to the
+ * underlying 3D API.
+ * if flushRenderTarget is true then after the call the last
+ * rendertarget set will be current in the underlying 3D API, otherwise
+ * it may not be. It is useful to set if the caller plans to use the 3D
+ * context outside of Ganesh to render into the current RT.
+ */
+ void flush(bool flushRenderTarget);
+
+ /**
+ * Return true on success, i.e. if we could copy the specified range of
+ * pixels from the current render-target into the buffer, converting into
+ * the specified pixel-config.
+ */
+ bool readPixels(int left, int top, int width, int height,
+ GrTexture::PixelConfig, void* buffer);
+
+ /**
+ * Copy the src pixels [buffer, stride, pixelconfig] into the current
+ * render-target at the specified rectangle.
+ */
+ void writePixels(int left, int top, int width, int height,
+ GrTexture::PixelConfig, const void* buffer, size_t stride);
+
+ /* -------------------------------------------------------
+ * Mimicking the GrGpu interface for now
+ * TODO: define appropriate higher-level API for context
+ */
+
+ GrVertexBuffer* createVertexBuffer(uint32_t size, bool dynamic);
+
+ GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic);
+
+ bool reserveAndLockGeometry(GrVertexLayout vertexLayout,
+ uint32_t vertexCount,
+ uint32_t indexCount,
+ void** vertices,
+ void** indices);
+
+ void drawIndexed(GrGpu::PrimitiveType type,
+ uint32_t startVertex,
+ uint32_t startIndex,
+ uint32_t vertexCount,
+ uint32_t indexCount);
+
+ void drawNonIndexed(GrGpu::PrimitiveType type,
+ uint32_t startVertex,
+ uint32_t vertexCount);
+
+ void setVertexSourceToArray(const void* array,
+ GrVertexLayout vertexLayout);
+ void setIndexSourceToArray(const void* array);
+ void setVertexSourceToBuffer(GrVertexBuffer* buffer,
+ GrVertexLayout vertexLayout);
+ void setIndexSourceToBuffer(GrIndexBuffer* buffer);
+
+ void releaseReservedGeometry();
+
+ void resetStats();
+
+ const GrGpu::Stats& getStats() const;
+
+ void printStats() const;
+
+ class AutoRenderTarget : ::GrNoncopyable {
+ public:
+ AutoRenderTarget(GrContext* context, GrRenderTarget* target) {
+ fContext = NULL;
+ fPrevTarget = context->currentRenderTarget();
+ if (fPrevTarget != target) {
+ context->setRenderTarget(target);
+ fContext = context;
+ }
+ }
+ ~AutoRenderTarget() {
+ if (fContext) {
+ fContext->setRenderTarget(fPrevTarget);
+ }
+ }
+ private:
+ GrContext* fContext;
+ GrRenderTarget* fPrevTarget;
+ };
+
+ /* -------------------------------------------------------
+ */
+
+ // Intended only to be used within Ganesh:
+ GrGpu* getGpu() { return fGpu; }
+ GrFontCache* getFontCache() { return fFontCache; }
+ GrDrawTarget* getTextTarget();
+ void flushText();
+
+ const GrIndexBuffer* quadIndexBuffer() const;
+ int maxQuadsInIndexBuffer() const;
+
+private:
+ GrGpu* fGpu;
+ GrTextureCache* fTextureCache;
+ GrFontCache* fFontCache;
+
+ GrVertexBufferAllocPool fVBAllocPool;
+ GrInOrderDrawBuffer fTextDrawBuffer;
+
+ GrContext(GrGpu* gpu);
+ bool finalizeTextureKey(GrTextureKey*, const GrSamplerState&) const;
+
+ void drawClipIntoStencil();
+};
+
+/**
+ * Save/restore the view-matrix in the context.
+ */
+class GrAutoViewMatrix : GrNoncopyable {
+public:
+ GrAutoViewMatrix(GrContext* ctx) : fContext(ctx) {
+ ctx->getViewMatrix(&fMatrix);
+ }
+ GrAutoViewMatrix(GrContext* ctx, const GrMatrix& matrix) : fContext(ctx) {
+ ctx->getViewMatrix(&fMatrix);
+ ctx->setViewMatrix(matrix);
+ }
+ ~GrAutoViewMatrix() {
+ fContext->setViewMatrix(fMatrix);
+ }
+
+private:
+ GrContext* fContext;
+ GrMatrix fMatrix;
+};
+
+#endif
+ diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h new file mode 100644 index 0000000000..fee13a6c7e --- /dev/null +++ b/gpu/include/GrDrawTarget.h @@ -0,0 +1,736 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrDrawTarget_DEFINED +#define GrDrawTarget_DEFINED + +#include "GrScalar.h" +#include "GrMatrix.h" +#include "GrColor.h" +#include "GrRefCnt.h" +#include "GrSamplerState.h" +#include "GrClip.h" + +class GrTexture; +class GrRenderTarget; +class GrClipIterator; +class GrVertexBuffer; +class GrIndexBuffer; + +class GrDrawTarget : public GrRefCnt { +public: + /** + * Geometric primitives used for drawing. + */ + enum PrimitiveType { + kTriangles_PrimitiveType, + kTriangleStrip_PrimitiveType, + kTriangleFan_PrimitiveType, + kPoints_PrimitiveType, + kLines_PrimitiveType, + kLineStrip_PrimitiveType + }; + + /** + * Flags that affect rendering. Controlled using enable/disableState(). All + * default to disabled. + */ + enum StateBits { + kDither_StateBit = 0x1,//<! Perform color dithering + kAntialias_StateBit = 0x2,//<! Perform anti-aliasing. The render- + // target must support some form of AA + // (msaa, coverage sampling, etc). For + // GrGpu-created rendertarget/textures + // this is controlled by parameters + // passed to createTexture. + kClip_StateBit = 0x4,//<! Controls whether drawing is clipped + // against the region specified by + // setClip. + }; + + /** + * Coeffecients for alpha-blending. + */ + enum BlendCoeff { + kZero_BlendCoeff, //<! 0 + kOne_BlendCoeff, //<! 1 + kSC_BlendCoeff, //<! src color + kISC_BlendCoeff, //<! one minus src color + kDC_BlendCoeff, //<! dst color + kIDC_BlendCoeff, //<! one minus dst color + kSA_BlendCoeff, //<! src alpha + kISA_BlendCoeff, //<! one minus src alpha + kDA_BlendCoeff, //<! dst alpha + kIDA_BlendCoeff, //<! one minus dst alpha + }; + + /** + * StencilPass + * + * Sets the stencil state for subsequent draw calls. Used to fill paths. + * + * Winding requires two passes when the GPU/API doesn't support separate + * stencil. + * + * The color pass for path fill is used to zero out stencil bits used for + * path filling. Every pixel covere by a winding/EO stencil pass must get + * covered by the color pass in order to leave stencil buffer in the correct + * state for the next path draw. + * + * NOTE: Stencil-based Winding fill has alias-to-zero problems. (e.g. A + * winding count of 128,256,512,etc with a 8 bit stencil buffer + * will be unfilled) + */ + enum StencilPass { + kNone_StencilPass, //<! Not drawing a path or clip. + kEvenOddStencil_StencilPass, //<! records in/out in stencil buffer + // using the Even/Odd fill rule. + kEvenOddColor_StencilPass, //<! writes colors to color target in + // pixels marked inside the fill by + // kEOFillStencil_StencilPass. Clears + // stencil in pixels covered by + // geometry. + kWindingStencil1_StencilPass, //<! records in/out in stencil buffer + // using the Winding fill rule. + kWindingStencil2_StencilPass, //<! records in/out in stencil buffer + // using the Winding fill rule. + // Run when single-stencil-pass winding + // not supported (i.e. no separate + // stencil support) + kWindingColor_StencilPass, //<! writes colors to color target in + // pixels marked inside the fill by + // kWindFillStencil_StencilPass. Clears + // stencil in pixels covered by + // geometry. + kDrawTargetCount_StencilPass //<! Subclass may extend this enum to use + // the stencil for other purposes (e.g. + // to do stencil-based clipping) + // This value is provided as basis for + // defining these extended enum values. + }; + +protected: + enum MatrixMode { + kModelView_MatrixMode = 0, + kTexture_MatrixMode, + + kMatrixModeCount + }; + + struct DrawState { + uint32_t fFlagBits; + BlendCoeff fSrcBlend; + BlendCoeff fDstBlend; + GrTexture* fTexture; + GrSamplerState fSamplerState; + GrRenderTarget* fRenderTarget; + GrColor fColor; + float fPointSize; + StencilPass fStencilPass; + bool fReverseFill; + GrMatrix fMatrixModeCache[kMatrixModeCount]; + bool operator ==(const DrawState& s) const { + return 0 == memcmp(this, &s, sizeof(DrawState)); + } + bool operator !=(const DrawState& s) const { return !(*this == s); } + }; + +public: + /////////////////////////////////////////////////////////////////////////// + + GrDrawTarget(); + + /** + * Sets the current clip to the region specified by clip. All draws will be + * clipped against this clip if kClip_StateBit is enabled. + * + * @param description of the clipping region + */ + void setClip(const GrClip& clip); + + /** + * Gets the current clip. + * + * @return the clip. + */ + const GrClip& getClip() const; + + /** + * Sets the texture used at the next drawing call + * + * @param texture The texture to set. Can be NULL though there is no advantage + * to settings a NULL texture if doing non-textured drawing + */ + void setTexture(GrTexture* texture); + + /** + * Retrieves the currently set texture. + * + * @return The currently set texture. The return value will be NULL if no + * texture has been set, NULL was most recently passed to + * setTexture, or the last setTexture was destroyed. + */ + GrTexture* currentTexture() const; + + /** + * Sets the rendertarget used at the next drawing call + * + * @param target The render target to set. Must be a valid rendertarget. + * That is it is a value that was returned by + * currentRenderTarget() or GrTexture::asRenderTarget(). + */ + void setRenderTarget(GrRenderTarget* target); + + /** + * Retrieves the currently set rendertarget. + * + * @return The currently set render target. + */ + GrRenderTarget* currentRenderTarget() const; + + /** + * Sets the sampler state for the next draw. + * + * The sampler state determines the address wrap modes and + * filtering + * + * @param samplerState Specifies the sampler state. + */ + void setSamplerState(const GrSamplerState& samplerState); + + /** + * Sets the matrix applied to texture coordinates. + * + * The post-matrix texture coordinates in the square [0,1]^2 cover the + * entire area of the texture. This means the full POT width when a NPOT + * texture is embedded in a POT width texture to meet the 3D API + * requirements. The texture matrix is applied both when the texture + * coordinates are explicit and when vertex positions are used as texture + * coordinates. In the latter case the texture matrix is applied to the + * pre-modelview position values. + * + * @param m the matrix used to transform the texture coordinates. + */ + void setTextureMatrix(const GrMatrix& m) { + this->loadMatrix(m, kTexture_MatrixMode); + } + + /** + * Sets the matrix applied to veretx positions. + * + * In the post-view-matrix space the rectangle [0,w]x[0,h] + * fully covers the render target. (w and h are the width and height of the + * the rendertarget.) + * + * @param m the matrix used to transform the vertex positions. + */ + void setViewMatrix(const GrMatrix& m) { + this->loadMatrix(m, kModelView_MatrixMode); + } + + /** + * Multiplies the current view matrix by a matrix + * + * After this call V' = V*m where V is the old view matrix, + * m is the parameter to this function, and V' is the new view matrix. + * (We consider positions to be column vectors so position vector p is + * transformed by matrix X as p' = X*p.) + * + * @param m the matrix used to modify the modelview matrix. + */ + void concatViewMatrix(const GrMatrix& m); + + /** + * Sets color for next draw to a premultiplied-alpha color. + * + * @param the color to set. + */ + void setColor(GrColor); + + /** + * Sets the color to be used for the next draw to be + * (r,g,b,a) = (alpha, alpha, alpha, alpha). + * + * @param alpha The alpha value to set as the color. + */ + void setAlpha(uint8_t alpha); + + /** + * Sets pass for path rendering + * + * @param pass of path rendering + */ + void setStencilPass(StencilPass pass); + + /** + * Reveses the in/out decision of the fill rule for path rendering. + * Only affects kEOFillColor_StencilPass and kWindingFillColor_StencilPass + * + * @param reverse true to reverse, false otherwise + */ + void setReverseFill(bool reverse); + + /** + * Enable render state settings. + * + * @param flags bitfield of StateBits specifing the states to enable + */ + void enableState(uint32_t stateBits); + + /** + * Disable render state settings. + * + * @param flags bitfield of StateBits specifing the states to disable + */ + void disableState(uint32_t stateBits); + + bool isDitherState() const { + return fCurrDrawState.fFlagBits & kDither_StateBit; + } + + /** + * Sets the size of points used the next time points are drawn. + * + * @param the point size + */ + void setPointSize(float size); + + /** + * Sets the blending function coeffecients. + * + * The blend function will be: + * D' = sat(S*srcCoef + D*dstCoef) + * + * where D is the existing destination color, S is the incoming source + * color, and D' is the new destination color that will be written. sat() + * is the saturation function. + * + * @param srcCoef coeffecient applied to the src color. + * @param dstCoef coeffecient applied to the dst color. + */ + void setBlendFunc(BlendCoeff srcCoef, BlendCoeff dstCoef); + + /** + * Retrieves the current view matrix + * @param matrix will be the current view matrix after return. + */ + void getViewMatrix(GrMatrix* matrix) const; + + /** + * Retrieves the inverse of the current view matrix. + * + * If the current view matrix is invertible, return true, and if matrix + * is non-null, copy the inverse into it. If the current view matrix is + * non-invertible, return false and ignore the matrix parameter. + * + * @param matrix if not null, will receive a copy of the current inverse. + */ + bool getViewInverse(GrMatrix* matrix) const; + + /** + * Used to save and restore the GrGpu's drawing state + */ + struct SavedDrawState { + private: + DrawState fState; + friend class GrDrawTarget; + }; + + /** + * Saves the current draw state. The state can be restored at a later time + * with restoreDrawState. + * + * See also AutoStateRestore class. + * + * @param state will hold the state after the function returns. + */ + void saveCurrentDrawState(SavedDrawState* state) const; + + /** + * Restores previously saved draw state. The client guarantees that state + * was previously passed to saveCurrentDrawState and that the rendertarget + * and texture set at save are still valid. + * + * See also AutoStateRestore class. + * + * @param state the previously saved state to restore. + */ + void restoreDrawState(const SavedDrawState& state); + + /** + * Copies the draw state from another target to this target. + * + * @param srcTarget draw target used as src of the draw state. + */ + void copyDrawState(const GrDrawTarget& srcTarget); + + /** + * Flags that indicate the layout of vertex data. + * + * kSeparateTexCoord_VertexLayoutBit is incompatible with + * kPositionAsTexCoord_VertexLayoutBit. kTextFormat_VertexLayoutBit is + * incompatible with any other flags. + * + * When kTextFormat_VertexLayoutBit is set: + * Texture coordinates are separate. + * Positions and Texture coordinates are SkGpuTextVertex. + * For non-text vertices: + * Position and texture coordinates are GrPoints. + * Colors are GrColors. + * + * The order is always positions, texture coords, colors. + */ + enum VertexLayoutBits { + kSeparateTexCoord_VertexLayoutBit = 0x1, //<! vertices have texture + // coords that are not + // inferred from the + // positions + kPositionAsTexCoord_VertexLayoutBit = 0x2, //<! vertices use positions + // as texture coords. + kColor_VertexLayoutBit = 0x4, //<! vertices have colors + kTextFormat_VertexLayoutBit = 0x8, //<! vertices represent glyphs + // and therefore contain + // two GrGpuTextVertexs. + // One for pos and one for + // text coords. + // for below assert + kDummy, + kHighVertexLayoutBit = kDummy - 1 + }; + GR_STATIC_ASSERT(kHighVertexLayoutBit < (1 << 8*sizeof(GrVertexLayout))); + + /** + * Reserves space for vertices and/or indices. Draw target will use + * reserved vertices / indices at next draw. + * + * If succeeds: + * if vertexCount is nonzero, *vertices will be the array + * of vertices to be filled by caller. The next draw will read + * these vertices. + * + * if indecCount is nonzero, *indices will be the array of indices + * to be filled by caller. The next indexed draw will read from + * these indices. + * + * If a client does not already have a vertex buffer or cpu arrays then this + * is the preferred way to allocate vertex/index array. It allows the + * subclass of GrDrawTarget to decide whether to put data in buffers, to + * group vertex data that uses the same state (e.g. for deferred rendering), + * etc. + * + * This must be matched with a releaseReservedGeometry call after all + * draws that reference the reserved geometry data have been called. + * + * AutoGeometryRelease can be used to automatically call the release. + * + * @param vertexCount the number of vertices to reserve space for. Can be 0. + * @param indexCount the number of indices to reserve space for. Can be 0. + * @param vertexLayout the format of vertices (ignored if vertexCount == 0). + * @param vertices will point to reserved vertex space if vertexCount is + * non-zero. Illegal to pass NULL if vertexCount > 0. + * @param indices will point to reserved index space if indexCount is + * non-zero. Illegal to pass NULL if indexCount > 0. + * + * @return true if succeeded in allocating space for the vertices and false + * if not. + */ + bool reserveAndLockGeometry(GrVertexLayout vertexLayout, + uint32_t vertexCount, + uint32_t indexCount, + void** vertices, + void** indices); + /** + * Provides hints to caller about the number of vertices and indices + * that can be allocated cheaply. This can be useful if caller is reserving + * space but doesn't know exactly how much geometry is needed. + * + * Also may hint whether the draw target should be flushed first. This is + * useful for deferred targets. + * + * @param vertexLayout layout of vertices caller would like to reserve + * @param vertexCount in: hint about how many vertices the caller would + * like to allocate. + * out: a hint about the number of vertices that can be + * allocated cheaply. Negative means no hint. + * Ignored if NULL. + * @param indexCount in: hint about how many indices the caller would + * like to allocate. + * out: a hint about the number of indices that can be + * allocated cheaply. Negative means no hint. + * Ignored if NULL. + * + * @return true if target should be flushed based on the input values. + */ + virtual bool geometryHints(GrVertexLayout vertexLayout, + int32_t* vertexCount, + int32_t* indexCount) const; + + /** + * Releases reserved vertex/index data from reserveAndLockGeometry(). + */ + void releaseReservedGeometry(); + + /** + * Sets source of vertex data for the next draw. Data does not have to be + * in the array until drawIndexed or drawNonIndexed. + * + * @param array cpu array containing vertex data. + * @param vertexLayout layout of the vertex data in the array. + */ + void setVertexSourceToArray(const void* array, GrVertexLayout vertexLayout); + + /** + * Sets source of index data for the next indexed draw. Data does not have + * to be in the array until drawIndexed or drawNonIndexed. + * + * @param array cpu array containing index data. + */ + void setIndexSourceToArray(const void* array); + + /** + * Sets source of vertex data for the next draw. Data does not have to be + * in the buffer until drawIndexed or drawNonIndexed. + * + * @param buffer vertex buffer containing vertex data. Must be + * unlocked before draw call. + * @param vertexLayout layout of the vertex data in the buffer. + */ + void setVertexSourceToBuffer(const GrVertexBuffer* buffer, + GrVertexLayout vertexLayout); + + /** + * Sets source of index data for the next indexed draw. Data does not have + * to be in the buffer until drawIndexed or drawNonIndexed. + * + * @param buffer index buffer containing indices. Must be unlocked + * before indexed draw call. + */ + void setIndexSourceToBuffer(const GrIndexBuffer* buffer); + + /** + * Draws indexed geometry using the current state and current vertex / index + * sources. + * + * @param type The type of primitives to draw. + * @param startVertex the vertex in the vertex array/buffer corresponding + * to index 0 + * @param startIndex first index to read from index src. + * @param vertexCount one greater than the max index. + * @param indexCount the number of index elements to read. The index count + * is effectively trimmed to the last completely + * specified primitive. + */ + virtual void drawIndexed(PrimitiveType type, + uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount) = 0; + + /** + * Draws non-indexed geometry using the current state and current vertex + * sources. + * + * @param type The type of primitives to draw. + * @param startVertex the vertex in the vertex array/buffer corresponding + * to index 0 + * @param vertexCount one greater than the max index. + */ + virtual void drawNonIndexed(PrimitiveType type, + uint32_t startVertex, + uint32_t vertexCount) = 0; + + /////////////////////////////////////////////////////////////////////////// + + class AutoStateRestore : ::GrNoncopyable { + public: + AutoStateRestore(GrDrawTarget* target); + ~AutoStateRestore(); + + private: + GrDrawTarget* fDrawTarget; + SavedDrawState fDrawState; + }; + + /////////////////////////////////////////////////////////////////////////// + + class AutoReleaseGeometry : ::GrNoncopyable { + public: + AutoReleaseGeometry(GrDrawTarget* target, + GrVertexLayout vertexLayout, + uint32_t vertexCount, + uint32_t indexCount) { + fTarget = target; + fSuccess = fTarget->reserveAndLockGeometry(vertexLayout, + vertexCount, + indexCount, + &fVertices, + &fIndices); + } + ~AutoReleaseGeometry() { + if (fSuccess) { + fTarget->releaseReservedGeometry(); + } + } + + bool succeeded() const { return fSuccess; } + void* vertices() const { return fVertices; } + void* indices() const { return fIndices; } + + GrPoint* positions() const { + return static_cast<GrPoint*>(fVertices); + } + + private: + GrDrawTarget* fTarget; + bool fSuccess; + void* fVertices; + void* fIndices; + }; + + /////////////////////////////////////////////////////////////////////////// + + class AutoClipRestore : ::GrNoncopyable { + public: + AutoClipRestore(GrDrawTarget* target) { + fTarget = target; + fClip = fTarget->getClip(); + } + + ~AutoClipRestore() { + fTarget->setClip(fClip); + } + private: + GrDrawTarget* fTarget; + GrClip fClip; + }; + + //////////////////////////////////////////////////////////////////////////// + + /** + * Helper function to compute the size of a vertex from a vertex layout + * @return size of a single vertex. + */ + static size_t VertexSize(GrVertexLayout vertexLayout); + + /** + * Helper function to compute the offset of texture coordinates in a vertex + * @return offset of texture coordinates in vertex layout or -1 if the + * layout has no texture coordinates. + */ + static int VertexTexCoordOffset(GrVertexLayout vertexLayout); + + /** + * Helper function to compute the offset of the color in a vertex + * @return offset of color in vertex layout or -1 if the + * layout has no color. + */ + static int VertexColorOffset(GrVertexLayout vertexLayout); + + /** + * Helper function to compute vertex size and component offsets. + * @param texCoordOffset after return it is the offset of texture coords + * in vertex layout or -1 if the layout has no + * texture coords. + * @param colorOffset after return it is the offset of color in vertex + * layout or -1 if the layout has no color. + * @return size of a single vertex. + */ + static int VertexSizeAndOffsets(GrVertexLayout vertexLayout, + int* texCoordOffset, + int* colorOffset); + /** + * Helper function to determine if vertex layout contains either explicit or + * implicit texture coordinates. + * + * @return true if vertex specifies texture coordinates, false otherwise. + */ + static bool VertexHasTexCoords(GrVertexLayout vertexLayout); + +protected: + + // Helpers for GrDrawTarget subclasses that won't have private access to + // SavedDrawState but need to peek at the state values. + static DrawState& accessSavedDrawState(SavedDrawState& sds) + { return sds.fState; } + static const DrawState& accessSavedDrawState(const SavedDrawState& sds) + { return sds.fState; } + + // implemented by subclass + virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout, + void** vertices, + void** indices) = 0; + + virtual void releaseGeometryHelper() = 0; + + virtual void clipWillChange(const GrClip& clip) = 0; + + enum GeometrySrcType { + kArray_GeometrySrcType, + kReserved_GeometrySrcType, + kBuffer_GeometrySrcType + }; + + struct { + bool fLocked; + uint32_t fVertexCount; + uint32_t fIndexCount; + } fReservedGeometry; + + struct GeometrySrc { + GeometrySrcType fVertexSrc; + union { + const GrVertexBuffer* fVertexBuffer; + const void* fVertexArray; + }; + GeometrySrcType fIndexSrc; + union { + const GrIndexBuffer* fIndexBuffer; + const void* fIndexArray; + }; + GrVertexLayout fVertexLayout; + } fGeometrySrc; + + GrClip fClip; + + DrawState fCurrDrawState; + + // set texture or modelview matrix + void loadMatrix(const GrMatrix&, MatrixMode); + + // not meant for outside usage. Could cause problems if calls between + // the save and restore mess with reserved geometry state. + class AutoGeometrySrcRestore { + public: + AutoGeometrySrcRestore(GrDrawTarget* target) { + fTarget = target; + fGeometrySrc = fTarget->fGeometrySrc; + } + ~AutoGeometrySrcRestore() { + fTarget->fGeometrySrc = fGeometrySrc; + } + private: + GrDrawTarget *fTarget; + GeometrySrc fGeometrySrc; + + AutoGeometrySrcRestore(); + AutoGeometrySrcRestore(const AutoGeometrySrcRestore&); + AutoGeometrySrcRestore& operator =(AutoGeometrySrcRestore&); + }; + +}; + +#endif diff --git a/gpu/include/GrFontScaler.h b/gpu/include/GrFontScaler.h new file mode 100644 index 0000000000..6baa56fff3 --- /dev/null +++ b/gpu/include/GrFontScaler.h @@ -0,0 +1,43 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrFontScaler_DEFINED +#define GrFontScaler_DEFINED + +#include "GrGlyph.h" +#include "GrKey.h" + +class GrPath; + +/** + * This is a virtual base class which Gr's interface to the host platform's + * font scaler. + * + * The client is responsible for subclassing, and instantiating this. The + * instance is create for a specific font+size+matrix. + */ +class GrFontScaler : public GrRefCnt { +public: + virtual const GrKey* getKey() = 0; + virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds) = 0; + virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height, + int rowBytes, void* image) = 0; + virtual bool getGlyphPath(uint16_t glyphID, GrPath*) = 0; +}; + +#endif + diff --git a/gpu/include/GrGLConfig.h b/gpu/include/GrGLConfig.h new file mode 100644 index 0000000000..90763abc5c --- /dev/null +++ b/gpu/include/GrGLConfig.h @@ -0,0 +1,323 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGLConfig_DEFINED +#define GrGLConfig_DEFINED + +#include "GrTypes.h" + +#if GR_WIN32_BUILD + // glew has to be included before gl + #define GR_INCLUDE_GLDESKTOP <GL/glew.h> + #define GR_INCLUDE_GLDESKTOPext <GL/gl.h> + #define GR_GL_FUNC __stdcall + // undo stupid windows defines + #undef near + #undef far +#elif GR_MAC_BUILD + #define GR_INCLUDE_GLDESKTOP <OpenGL/gl.h> + #define GR_INCLUDE_GLDESKTOPext <OpenGL/glext.h> + #define GR_GL_FUNC +#elif GR_IOS_BUILD + #define GR_INCLUDE_GLES1 <OpenGLES/ES1/gl.h> + #define GR_INCLUDE_GLES1ext <OpenGLES/ES1/glext.h> + #define GR_INCLUDE_GLES2 <OpenGLES/ES2/gl.h> + #define GR_INCLUDE_GLES2ext <OpenGLES/ES2/glext.h> + #define GR_GL_FUNC +#elif GR_ANDROID_BUILD + #ifndef GL_GLEXT_PROTOTYPES + #define GL_GLEXT_PROTOTYPES + #endif + #define GR_INCLUDE_GLES2 <GLES2/gl2.h> + #define GR_INCLUDE_GLES2ext <GLES2/gl2ext.h> + #define GR_GL_FUNC +#elif GR_LINUX_BUILD + // need to distinguish between ES and Deskop versions for linux + #ifndef GL_GLEXT_PROTOTYPES + #define GL_GLEXT_PROTOTYPES + #endif + #define GR_INCLUDE_GLES1 <GLES/gl.h> + #define GR_INCLUDE_GLES1ext <GLES/glext.h> + #define GR_INCLUDE_GLES2 <GLES2/gl2.h> + #define GR_INCLUDE_GLES2ext <GLES2/gl2ext.h> + #define GR_GL_FUNC +#elif GR_QNX_BUILD + #ifndef GL_GLEXT_PROTOTYPES + #define GL_GLEXT_PROTOTYPES + #endif + // This is needed by the QNX GLES2 headers + #define GL_API_EXT + #define GR_INCLUDE_GLES2 <GLES2/gl2.h> + #define GR_INCLUDE_GLES2ext <GLES2/gl2ext.h> + #define GR_INCLUDE_EGL <EGL/egl.h> + #define GR_GL_FUNC +#else + #error "unsupported GR_???_BUILD" +#endif + +// Ensure we're at least defined +// + +#ifndef GR_SUPPORT_GLES1 + #if defined(GR_INCLUDE_GLES1) + #define GR_SUPPORT_GLES1 1 + #else + #define GR_SUPPORT_GLES1 0 + #endif +#endif + +#ifndef GR_SUPPORT_GLES2 + #if defined(GR_INCLUDE_GLES2) + #define GR_SUPPORT_GLES2 1 + #else + #define GR_SUPPORT_GLES2 0 + #endif +#endif + +#ifndef GR_SUPPORT_GLDESKTOP + #if defined(GR_INCLUDE_GLDESKTOP) + #define GR_SUPPORT_GLDESKTOP 1 + #else + #define GR_SUPPORT_GLDESKTOP 0 + #endif +#endif + +#ifndef GR_SUPPORT_EGL + #if defined(GR_INCLUDE_EGL) + #define GR_SUPPORT_EGL 1 + #else + #define GR_SUPPORT_EGL 0 + #endif +#endif +// Filter the includes based on what we support +// + +#if !GR_SUPPORT_GLES1 + #undef GR_INCLUDE_GLES1 + #undef GR_INCLUDE_GLES1ext +#endif + +#if !GR_SUPPORT_GLES2 + #undef GR_INCLUDE_GLES2 + #undef GR_INCLUDE_GLES2ext +#endif + +#if !GR_SUPPORT_GLDESKTOP + #undef GR_INCLUDE_GLDESKTOP + #undef GR_INCLUDE_GLDESKTOPext +#endif + +#if !GR_SUPPORT_EGL + #undef GR_INCLUDE_EGL +#endif + +// Begin including GL headers +// + +#ifdef GR_INCLUDE_GLES1 + #include GR_INCLUDE_GLES1 +#endif +#ifdef GR_INCLUDE_GLES1ext + #include GR_INCLUDE_GLES1ext +#endif +#ifdef GR_INCLUDE_GLES2 + #include GR_INCLUDE_GLES2 +#endif +#ifdef GR_INCLUDE_GLES2ext + #include GR_INCLUDE_GLES2ext +#endif +#ifdef GR_INCLUDE_GLDESKTOP + #include GR_INCLUDE_GLDESKTOP +#endif +#ifdef GR_INCLUDE_GLDESKTOPext + #include GR_INCLUDE_GLDESKTOPext +#endif +#ifdef GR_INCLUDE_EGL + #include GR_INCLUDE_EGL +#endif + +// +// End including GL headers + +#if GL_VERSION_1_1 + #define GR_GL_DESKTOP 1 + #define GR_GL_ES 0 +#else + #ifndef GL_ES_VERSION_2_0 + GR_STATIC_ASSERT(GL_VERSION_ES_CM_1_0 || + GL_VERSION_ES_CL_1_0 || + GL_VERSION_ES_CM_1_1 || + GL_VERSION_ES_CL_1_1); + #endif + #define GR_GL_DESKTOP 0 + #define GR_GL_ES 1 +#endif + +#if GR_SCALAR_IS_FIXED + #define GrGLType GL_FIXED +#elif GR_SCALAR_IS_FLOAT + #define GrGLType GL_FLOAT +#else + #error "unknown GR_SCALAR type" +#endif + +#if GR_TEXT_SCALAR_IS_USHORT + #define GrGLTextType GL_UNSIGNED_SHORT + #define GR_GL_TEXT_TEXTURE_NORMALIZED 1 +#elif GR_TEXT_SCALAR_IS_FLOAT + #define GrGLTextType GL_FLOAT + #define GR_GL_TEXT_TEXTURE_NORMALIZED 0 +#elif GR_TEXT_SCALAR_IS_FIXED + #define GrGLTextType GL_FIXED + #define GR_GL_TEXT_TEXTURE_NORMALIZED 0 +#else + #error "unknown GR_TEXT_SCALAR type" +#endif + +// Pick a pixel config for 32bit bitmaps. Our default is GL_RGBA +#ifndef SK_GL_32BPP_COLOR_FORMAT + #define SK_GL_32BPP_COLOR_FORMAT GL_RGBA +#endif + +//////////////////////////////////////////////////////////////////////////////// +// setup for opengl ES/desktop extensions +// we make a struct of function pointers so that each GL context +// can have it's own struct. (Some environments may have different proc +// addresses for different contexts). + +extern "C" { +struct GrGLExts { +// FBO + GLvoid (GR_GL_FUNC *GenFramebuffers)(GLsizei n, GLuint *framebuffers); + GLvoid (GR_GL_FUNC *BindFramebuffer)(GLenum target, GLuint framebuffer); + GLvoid (GR_GL_FUNC *FramebufferTexture2D)(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level); + GLenum (GR_GL_FUNC *CheckFramebufferStatus)(GLenum target); + GLvoid (GR_GL_FUNC *DeleteFramebuffers)(GLsizei n, const + GLuint *framebuffers); + GLvoid (GR_GL_FUNC *RenderbufferStorage)(GLenum target, + GLenum internalformat, + GLsizei width, GLsizei height); + GLvoid (GR_GL_FUNC *GenRenderbuffers)(GLsizei n, GLuint *renderbuffers); + GLvoid (GR_GL_FUNC *DeleteRenderbuffers)(GLsizei n, + const GLuint *renderbuffers); + GLvoid (GR_GL_FUNC *FramebufferRenderbuffer)(GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + GLvoid (GR_GL_FUNC *BindRenderbuffer)(GLenum target, GLuint renderbuffer); + +// Multisampling + // same prototype for ARB_FBO, EXT_FBO, GL 3.0, & Apple ES extension + GLvoid (GR_GL_FUNC *RenderbufferStorageMultisample)(GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height); + // desktop: ext_fbo_blit, arb_fbo, gl 3.0 + GLvoid (GR_GL_FUNC *BlitFramebuffer)(GLint srcX0, GLint srcY0, + GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); + // apple's es extension + GLvoid (GR_GL_FUNC *ResolveMultisampleFramebuffer)(); + + // IMG'e es extension + GLvoid (GR_GL_FUNC *FramebufferTexture2DMultisample)(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level, + GLsizei samples); + +// Buffer mapping (extension in ES). + GLvoid* (GR_GL_FUNC *MapBuffer)(GLenum target, GLenum access); + GLboolean (GR_GL_FUNC *UnmapBuffer)(GLenum target); +}; +} + +// FBO +#define GR_FRAMEBUFFER 0x8D40 +#define GR_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GR_COLOR_ATTACHMENT0 0x8CE0 +#define GR_FRAMEBUFFER_BINDING 0x8CA6 +#define GR_RENDERBUFFER 0x8D41 +#define GR_STENCIL_ATTACHMENT 0x8D20 +#define GR_STENCIL_INDEX8 0x8D48 +#define GR_STENCIL_INDEX16 0x8D49 +#define GR_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GR_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GR_UNSIGNED_INT_24_8 0x84FA +#define GR_DEPTH_STENCIL 0x84F9 +#define GR_RGBA8 0x8058 +#define GR_RGB565 0x8D62 + + +// Multisampling + +// IMG MAX_SAMPLES uses a different value than desktop, Apple ES extension. +#define GR_MAX_SAMPLES 0x8D57 +#define GR_MAX_SAMPLES_IMG 0x9135 +#define GR_READ_FRAMEBUFFER 0x8CA8 +#define GR_DRAW_FRAMEBUFFER 0x8CA9 + +// Buffer mapping +#define GR_WRITE_ONLY 0x88B9 +#define GR_BUFFER_MAPPED 0x88BC + +// Palette texture +#define GR_PALETTE8_RGBA8 0x8B91 + +extern void GrGLInitExtensions(GrGLExts* exts); +//////////////////////////////////////////////////////////////////////////////// + +extern void GrGLCheckErr(const char* location, const char* call); + +static inline void GrGLClearErr() { + while (GL_NO_ERROR != glGetError()) {} +} + +// GR_FORCE_GLCHECKERR can be defined by GrUserConfig.h +#if defined(GR_FORCE_GLCHECKERR) + #define GR_LOCAL_CALL_CHECKERR GR_FORCE_GLCHECKERR +#else + #define GR_LOCAL_CALL_CHECKERR GR_DEBUG +#endif +static inline void GrDebugGLCheckErr(const char* location, const char* call) { +#if GR_LOCAL_CALL_CHECKERR + GrGLCheckErr(location, call); +#endif +} +#undef GR_LOCAL_CALL_CHECKERR + +#if GR_GL_LOG_CALLS + extern bool gPrintGL; + #define GR_GL(X) gl ## X; GrDebugGLCheckErr(GR_FILE_AND_LINE_STR, #X); if (gPrintGL) GrPrintf(GR_FILE_AND_LINE_STR "GL: " #X "\n") + #define GR_GL_NO_ERR(X) GrGLClearErr(); gl ## X; if (gPrintGL) GrPrintf(GR_FILE_AND_LINE_STR "GL: " #X "\n") + #define GR_GLEXT(exts, X) exts. X; GrDebugGLCheckErr(GR_FILE_AND_LINE_STR, #X); if (gPrintGL) GrPrintf(GR_FILE_AND_LINE_STR "GL: " #X "\n") + #define GR_GLEXT_NO_ERR(exts, X) GrGLClearErr(); exts. X; if (gPrintGL) GrPrintf(GR_FILE_AND_LINE_STR "GL: " #X "\n") +#else + #define GR_GL(X) gl ## X; GrDebugGLCheckErr(GR_FILE_AND_LINE_STR, #X) + #define GR_GL_NO_ERR(X) GrGLClearErr(); gl ## X + #define GR_GLEXT(exts, X) exts. X; GrDebugGLCheckErr(GR_FILE_AND_LINE_STR, #X) + #define GR_GLEXT_NO_ERR(exts, X) GrGLClearErr(); exts. X +#endif + +#endif + diff --git a/gpu/include/GrGLIndexBuffer.h b/gpu/include/GrGLIndexBuffer.h new file mode 100644 index 0000000000..5177b4b7f5 --- /dev/null +++ b/gpu/include/GrGLIndexBuffer.h @@ -0,0 +1,53 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGLIndexBuffer_DEFINED +#define GrGLIndexBuffer_DEFINED + +#include "GrIndexBuffer.h" +#include "GrGLConfig.h" + +class GrGpuGL; + +class GrGLIndexBuffer : public GrIndexBuffer { +protected: + GrGLIndexBuffer(GLuint id, + GrGpuGL* gl, + uint32_t sizeInBytes, + bool dynamic); +public: + virtual ~GrGLIndexBuffer(); + + GLuint bufferID() const; + + // overrides of GrIndexBuffer + virtual void abandon(); + virtual void* lock(); + virtual void unlock(); + virtual bool isLocked() const; + virtual bool updateData(const void* src, uint32_t srcSizeInBytes); +private: + GrGpuGL* fGL; + GLuint fBufferID; + void* fLockPtr; + + friend class GrGpuGL; + + typedef GrIndexBuffer INHERITED; +}; + +#endif diff --git a/gpu/include/GrGLTexture.h b/gpu/include/GrGLTexture.h new file mode 100644 index 0000000000..ada31512f5 --- /dev/null +++ b/gpu/include/GrGLTexture.h @@ -0,0 +1,166 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGLTexture_DEFINED +#define GrGLTexture_DEFINED + +#include "GrGLConfig.h" +#include "GrGpu.h" +#include "GrTexture.h" +#include "GrRect.h" + +class GrGpuGL; +class GrGLTexture; + +class GrGLRenderTarget : public GrRenderTarget { +protected: + + struct GLRenderTargetIDs { + GLuint fRTFBOID; + GLuint fTexFBOID; + GLuint fStencilRenderbufferID; + GLuint fMSColorRenderbufferID; + bool fOwnIDs; + }; + + GrGLRenderTarget(const GLRenderTargetIDs& ids, + const GrIRect& fViewport, + GrGLTexture* texture, + GrGpuGL* gl); + + void setViewport(const GrIRect& rect) { GrAssert(rect.height() <= 0); + fViewport = rect;} + + virtual uint32_t width() const { return fViewport.width(); } + virtual uint32_t height() const { return -fViewport.height(); } + +public: + virtual ~GrGLRenderTarget(); + + bool resolveable() const { return fRTFBOID != fTexFBOID; } + bool needsResolve() const { return fNeedsResolve; } + void setDirty(bool dirty) { fNeedsResolve = resolveable() && dirty; } + + GLuint renderFBOID() const { return fRTFBOID; } + GLuint textureFBOID() const { return fTexFBOID; } + + const GrIRect& viewport() const { return fViewport; } + void abandon(); + +private: + GrGpuGL* fGL; + GLuint fRTFBOID; + GLuint fTexFBOID; + GLuint fStencilRenderbufferID; + GLuint fMSColorRenderbufferID; + + // Should this object delete IDs when it is destroyed or does someone + // else own them. + bool fOwnIDs; + + // If there separate Texture and RenderTarget FBO IDs then the rendertarget + // must be resolved to the texture FBO before it is used as a texture. + bool fNeedsResolve; + + // when we switch to this rendertarget we want to set the viewport to + // only render to to content area (as opposed to the whole allocation) and + // we want the rendering to be at top left (GL has origin in bottom left) + GrIRect fViewport; + + friend class GrGpuGL; + friend class GrGLTexture; + + typedef GrRenderTarget INHERITED; +}; + +class GrGLTexture : public GrTexture { +public: + enum Orientation { + kBottomUp_Orientation, + kTopDown_Orientation, + }; + +protected: + struct GLTextureDesc { + uint32_t fContentWidth; + uint32_t fContentHeight; + uint32_t fAllocWidth; + uint32_t fAllocHeight; + PixelConfig fFormat; + GLuint fTextureID; + GLenum fUploadFormat; + GLenum fUploadByteCount; + GLenum fUploadType; + Orientation fOrientation; + }; + typedef GrGLRenderTarget::GLRenderTargetIDs GLRenderTargetIDs; + GrGLTexture(const GLTextureDesc& textureDesc, + const GLRenderTargetIDs& rtIDs, + GrGpuGL* gl); + +public: + virtual ~GrGLTexture(); + + // overloads of GrTexture + virtual void abandon(); + virtual bool isRenderTarget() const; + virtual GrRenderTarget* asRenderTarget(); + virtual void removeRenderTarget(); + virtual void uploadTextureData(uint32_t x, + uint32_t y, + uint32_t width, + uint32_t height, + const void* srcData); + virtual intptr_t getTextureHandle(); + + const GrSamplerState& samplerState() const { return fSamplerState; } + void setSamplerState(const GrSamplerState& state) + { fSamplerState = state; } + GLuint textureID() const { return fTextureID; } + + GLenum uploadFormat() const { return fUploadFormat; } + GLenum uploadByteCount() const { return fUploadByteCount; } + GLenum uploadType() const { return fUploadType; } + + // Ganesh assumes texture coordinates have their origin + // in the top-left corner of the image. OpenGL, however, + // has the origin in the lower-left corner. For content that + // is loaded by Ganesh we just push the content "upside down" + // (by GL's understanding of the world ) in glTex*Image and the + // addressing just works out. However, content generated by GL + // (FBO or externally imported texture) will be updside down + // and it is up to the GrGpuGL derivative to handle y-mirroing. + Orientation orientation() const { return fOrientation; } + +private: + GrSamplerState fSamplerState; + GLuint fTextureID; + GLenum fUploadFormat; + GLenum fUploadByteCount; + GLenum fUploadType; + Orientation fOrientation; + GrGLRenderTarget* fRenderTarget; + GrGpuGL* fGpuGL; + + static const GLenum gWrapMode2GLWrap[]; + + friend class GrGpuGL; + + typedef GrTexture INHERITED; +}; + +#endif diff --git a/gpu/include/GrGLVertexBuffer.h b/gpu/include/GrGLVertexBuffer.h new file mode 100644 index 0000000000..6b99f57e5f --- /dev/null +++ b/gpu/include/GrGLVertexBuffer.h @@ -0,0 +1,55 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGLVertexBuffer_DEFINED +#define GrGLVertexBuffer_DEFINED + +#include "GrVertexBuffer.h" +#include "GrGLConfig.h" + +class GrGpuGL; + +class GrGLVertexBuffer : public GrVertexBuffer { +protected: + GrGLVertexBuffer(GLuint id, + GrGpuGL* gl, + uint32_t sizeInBytes, + bool dynamic); + +public: + virtual ~GrGLVertexBuffer(); + + // overrides of GrVertexBuffer + virtual void abandon(); + virtual void* lock(); + virtual void unlock(); + virtual bool isLocked() const; + virtual bool updateData(const void* src, uint32_t srcSizeInBytes); + + GLuint bufferID() const; + +private: + GrGpuGL* fGL; + GLuint fBufferID; + void* fLockPtr; + + friend class GrGpuGL; + + typedef GrVertexBuffer INHERITED; +}; + +#endif diff --git a/gpu/include/GrGlyph.h b/gpu/include/GrGlyph.h new file mode 100644 index 0000000000..4a3b3072c7 --- /dev/null +++ b/gpu/include/GrGlyph.h @@ -0,0 +1,89 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGlyph_DEFINED +#define GrGlyph_DEFINED + +#include "GrPath.h" +#include "GrRect.h" + +class GrAtlas; + +/* Need this to be quad-state: + - complete w/ image + - just metrics + - failed to get image, but has metrics + - failed to get metrics + */ +struct GrGlyph { + typedef uint32_t PackedID; + + GrAtlas* fAtlas; + GrPath* fPath; + PackedID fPackedID; + GrIRect16 fBounds; + GrIPoint16 fAtlasLocation; + + void init(GrGlyph::PackedID packed, const GrIRect& bounds) { + fAtlas = NULL; + fPath = NULL; + fPackedID = packed; + fBounds.set(bounds); + fAtlasLocation.set(0, 0); + } + + void free() { + if (fPath) { + delete fPath; + fPath = NULL; + } + } + + int width() const { return fBounds.width(); } + int height() const { return fBounds.height(); } + bool isEmpty() const { return fBounds.isEmpty(); } + uint16_t glyphID() const { return UnpackID(fPackedID); } + + /////////////////////////////////////////////////////////////////////////// + + static inline unsigned ExtractSubPixelBitsFromFixed(GrFixed pos) { + // two most significant fraction bits from fixed-point + return (pos >> 14) & 3; + } + + static inline PackedID Pack(uint16_t glyphID, GrFixed x, GrFixed y) { + x = ExtractSubPixelBitsFromFixed(x); + y = ExtractSubPixelBitsFromFixed(y); + return (x << 18) | (y << 16) | glyphID; + } + + static inline GrFixed UnpackFixedX(PackedID packed) { + return ((packed >> 18) & 3) << 14; + } + + static inline GrFixed UnpackFixedY(PackedID packed) { + return ((packed >> 16) & 3) << 14; + } + + static inline uint16_t UnpackID(PackedID packed) { + return (uint16_t)packed; + } +}; + + +#endif + diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h new file mode 100644 index 0000000000..f1fdf01d50 --- /dev/null +++ b/gpu/include/GrGpu.h @@ -0,0 +1,446 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGpu_DEFINED +#define GrGpu_DEFINED + +#include "GrRect.h" +#include "GrRefCnt.h" +#include "GrDrawTarget.h" +#include "GrGpuVertex.h" +#include "GrTexture.h" +#include "GrMemory.h" + + +class GrGpu : public GrDrawTarget { + +public: + /** + * Possible 3D APIs that may be used by Ganesh. + */ + enum Engine { + kOpenGL_Shaders_Engine, + kOpenGL_Fixed_Engine, + kDirect3D9_Engine + }; + + /** + * Platform specific 3D context. + * For + * kOpenGL_Shaders_Engine use NULL + * kOpenGL_Fixed_Engine use NULL + * kDirect3D9_Engine use an IDirect3DDevice9* + */ + typedef void* Platform3DContext; + + /** + * Create an instance of GrGpu that matches the specified Engine backend. + * If the requested engine is not supported (at compile-time or run-time) + * this returns NULL. + */ + static GrGpu* Create(Engine, Platform3DContext context3D); + + /** + * Describes levels of support for non-power-of-two textures. + */ + enum NPOTTextureTypes { + /** + * no support for NPOT textures + */ + kNone_NPOTTextureType, + /** + * only clamp is supported for textures + */ + kNoRepeat_NPOTTextureType, + /** + * no texture restrictions at all, but rendertargets must be POW2 + */ + kNonRendertarget_NPOTTextureType, + /** + * no POW2 restrictions at all + */ + kFull_NPOTTextureType + }; + + /** + * Used to control the level of antialiasing available for a rendertarget. + * Anti-alias quality levels depend on the underlying API/GPU capabilities. + */ + enum AALevels { + kNone_AALevel, //<! No antialiasing available. + kLow_AALevel, //<! Low quality antialiased rendering. Actual + // interpretation is platform-dependent. + kMed_AALevel, //<! Medium quality antialiased rendering. Actual + // interpretation is platform-dependent. + kHigh_AALevel, //<! High quality antialiased rendering. Actual + // interpretation is platform-dependent. + }; + + + /** + * Optional bitfield flags that can be passed to createTexture. + */ + enum TextureFlags { + kRenderTarget_TextureFlag = 0x1, //<! Creates a texture that can be + // rendered to by calling + // GrGpu::setRenderTarget() with + // GrTexture::asRenderTarget(). + kNoPathRendering_TextureFlag = 0x2, //<! If the texture is used as a + // rendertarget but paths will not + // be rendered to it. + kDynamicUpdate_TextureFlag = 0x4 //!< Hint that the CPU may modify + // this texture after creation + }; + + enum { + /** + * For Index8 pixel config, the colortable must be 256 entries + */ + kColorTableSize = 256 * sizeof(GrColor) + }; + /** + * Describes a texture to be created. + */ + struct TextureDesc { + uint32_t fFlags; //!< bitfield of TextureFlags + GrGpu::AALevels fAALevel;//!< The level of antialiasing available + // for a rendertarget texture. Only + // flags contains + // kRenderTarget_TextureFlag. + uint32_t fWidth; //!< Width of the texture + uint32_t fHeight; //!< Height of the texture + GrTexture::PixelConfig fFormat; //!< Format of source data of the + // texture. Not guaraunteed to be the + // same as internal format used by + // 3D API. + }; + + /** + * Gpu usage statistics. + */ + struct Stats { + uint32_t fVertexCnt; //<! Number of vertices drawn + uint32_t fIndexCnt; //<! Number of indices drawn + uint32_t fDrawCnt; //<! Number of draws + + uint32_t fProgChngCnt;//<! Number of program changes (N/A for fixed) + + /* + * Number of times the texture is set in 3D API + */ + uint32_t fTextureChngCnt; + /* + * Number of times the render target is set in 3D API + */ + uint32_t fRenderTargetChngCnt; + /* + * Number of textures created (includes textures that are rendertargets). + */ + uint32_t fTextureCreateCnt; + /* + * Number of rendertargets created. + */ + uint32_t fRenderTargetCreateCnt; + }; + + //////////////////////////////////////////////////////////////////////////// + + GrGpu(); + virtual ~GrGpu(); + + /** + * The GrGpu object normally assumes that no outsider is setting state + * within the underlying 3D API's context/device/whatever. This call informs + * the GrGpu that the state was modified and it should resend. Shouldn't + * be called frequently for good performance. + */ + virtual void resetContext(); + + void unimpl(const char[]); + + /** + * Creates a texture object + * + * @param desc describes the texture to be created. + * @param srcData texel data to load texture. Begins with full-size + * palette data for paletted textures. Contains width* + * height texels. If NULL texture data is uninitialized. + * + * @return The texture object if successful, otherwise NULL. + */ + virtual GrTexture* createTexture(const TextureDesc& desc, + const void* srcData, size_t rowBytes) = 0; + /** + * Wraps an externally-created rendertarget in a GrRenderTarget. + * @param platformRenderTarget handle to the the render target in the + * underlying 3D API. Interpretation depends on + * GrGpu subclass in use. + * @param width width of the render target + * @param height height of the render target + */ + virtual GrRenderTarget* createPlatformRenderTarget( + intptr_t platformRenderTarget, + int width, int height) = 0; + + /** + * Creates a vertex buffer. + * + * @param size size in bytes of the vertex buffer + * @param dynamic hints whether the data will be frequently changed + * by either GrVertexBuffer::lock or + * GrVertexBuffer::updateData. + * + * @return The vertex buffer if successful, otherwise NULL. + */ + virtual GrVertexBuffer* createVertexBuffer(uint32_t size, bool dynamic) = 0; + + /** + * Creates an index buffer. + * + * @param size size in bytes of the index buffer + * @param dynamic hints whether the data will be frequently changed + * by either GrIndexBuffer::lock or + * GrIndexBuffer::updateData. + * + * @return The index buffer if successful, otherwise NULL. + */ + virtual GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic) = 0; + + /** + * Gets the default render target. This is the render target set in the + * 3D API at the time the GrGpu was created. + */ + virtual GrRenderTarget* defaultRenderTarget() = 0; + + /** + * At construction time the GrGpu infers the render target and viewport from + * the state of the underlying 3D API. However, a platform-specific resize + * event may occur. + * @param width new width of the default rendertarget + * @param height new height of the default rendertarget + */ + virtual void setDefaultRenderTargetSize(uint32_t width, uint32_t height) = 0; + + /** + * Erase the entire render target, ignoring any clips/scissors. + * + * This is issued to the GPU driver immediately. + */ + virtual void eraseColor(GrColor color) = 0; + + /** + * Are 8 bit paletted textures supported. + * + * @return true if 8bit palette textures are supported, false otherwise + */ + bool supports8BitPalette() const { return f8bitPaletteSupport; } + + /** + * If single stencil pass winding is supported then one stencil pass + * (kWindingStencil1_PathPass) is required to do winding rule path filling + * (or inverse winding rule). Otherwise, two passes are required + * (kWindingStencil1_PathPass followed by kWindingStencil2_PathPass). + * + * @return true if only a single stencil pass is needed. + */ + bool supportsSingleStencilPassWinding() const + { return fSingleStencilPassForWinding; } + + /** + * Checks whether locking vertex and index buffers is supported. + * + * @return true if locking is supported. + */ + bool supportsBufferLocking() const { return fBufferLockSupport; } + + /** + * Gets the minimum width of a render target. If a texture/rt is created + * with a width less than this size the GrGpu object will clamp it to this + * value. + */ + int minRenderTargetWidth() const { return fMinRenderTargetWidth; } + + /** + * Gets the minimum width of a render target. If a texture/rt is created + * with a height less than this size the GrGpu object will clamp it to this + * value. + */ + int minRenderTargetHeight() const { return fMinRenderTargetHeight; } + + /** + * Retrieves the level of NPOT texture support. Regardless of support level + * NPOT textures can always be created, but internally they may be imbedded + * in a POT texture. An exception is paletted textures which must be + * specified as a POT when npotTextureSupport() is not Full. + * + * @return the level of NPOT texture support. + */ + NPOTTextureTypes npotTextureSupport() const { return fNPOTTextureSupport; } + + // GrDrawTarget overrides + virtual void drawIndexed(PrimitiveType type, + uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount); + + virtual void drawNonIndexed(PrimitiveType type, + uint32_t startVertex, + uint32_t vertexCount); + + /** + * Determines if blend is effectively disabled. + * + * @return true if blend can be disabled without changing the rendering + * result given the current state including the vertex layout specified + * with the vertex source. + */ + bool canDisableBlend() const; + + /** + * Returns an index buffer that can be used to render quads. + * Indices are 0, 1, 2, 0, 2, 3, etc. + * Draw with kTriangles_PrimitiveType + */ + const GrIndexBuffer* quadIndexBuffer() const; + /** + * Gets the number of quads that can be rendered using quadIndexBuffer. + */ + int maxQuadsInIndexBuffer() const; + + /** + * Ensures that the current render target is actually set in the + * underlying 3D API. Used when client wants to use 3D API to directly + * render to the RT. + */ + virtual void forceRenderTargetFlush() = 0; + + virtual bool readPixels(int left, int top, int width, int height, + GrTexture::PixelConfig, void* buffer) = 0; + + + const Stats& getStats() const; + void resetStats(); + void printStats() const; + +protected: + /** + * Extensions to GrDrawTarget::StencilPass to implement stencil clipping + */ + enum GpuStencilPass { + kSetClip_StencilPass = kDrawTargetCount_StencilPass, + /* rendering a hard clip to the stencil + buffer. Subsequent draws with other + StencilPass values will be clipped + if kStencilClip_StateBit is set. */ + kGpuCount_StencilPass + }; + + /** + * Extensions to GrDrawTarget::StateBits to implement stencil clipping + */ + struct ClipState { + bool fClipInStencil; + bool fClipIsDirty; + GrRenderTarget* fStencilClipTarget; + } fClipState; + + virtual void clipWillChange(const GrClip& clip); + bool setupClipAndFlushState(PrimitiveType type); + + struct BoundsState { + bool fScissorEnabled; + GrIRect fScissorRect; + GrIRect fViewportRect; + }; + + // defaults to false, subclass can set true to support palleted textures + bool f8bitPaletteSupport; + + // defaults to false, subclass can set higher support level + NPOTTextureTypes fNPOTTextureSupport; + + // True if only one stencil pass is required to implement the winding path + // fill rule. Subclass responsible for setting this value. + bool fSingleStencilPassForWinding; + + // set by subclass to true if index and vertex buffers can be locked, false + // otherwise. + bool fBufferLockSupport; + + // set by subclass + int fMinRenderTargetWidth; + int fMinRenderTargetHeight; + + // overridden by API specific GrGpu-derived class to perform the draw call. + virtual void drawIndexedHelper(PrimitiveType type, + uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount) = 0; + + virtual void drawNonIndexedHelper(PrimitiveType type, + uint32_t vertexCount, + uint32_t numVertices) = 0; + + // called to program the vertex data, indexCount will be 0 if drawing non- + // indexed geometry. + virtual void setupGeometry(uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount) = 0; + + + // The GrGpu typically records the clients requested state and then flushes + // deltas from previous state at draw time. This function does the + // API-specific flush of the state + // returns false if current state is unsupported. + virtual bool flushGraphicsState(PrimitiveType type) = 0; + + // Sets the scissor rect, or disables if rect is NULL. + virtual void flushScissor(const GrIRect* rect) = 0; + + // GrGpu subclass removes the clip from the stencil buffer + virtual void eraseStencilClip() = 0; + + // GrDrawTarget overrides + virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout, + void** vertices, + void** indices); + virtual void releaseGeometryHelper(); + +private: + mutable GrIndexBuffer* fQuadIndexBuffer; // mutable so it can be + // created on-demand + + static const int MAX_VERTEX_SIZE = GR_CT_MAX(2*sizeof(GrPoint) + sizeof(GrColor), + 2*sizeof(GrGpuTextVertex)); + static const int VERTEX_STORAGE = 16 * MAX_VERTEX_SIZE; + static const int INDEX_STORAGE = 32 * sizeof(uint16_t); + +protected: + GrAutoSMalloc<VERTEX_STORAGE> fVertices; + GrAutoSMalloc<INDEX_STORAGE> fIndices; + + Stats fStats; + +private: + typedef GrRefCnt INHERITED; +}; + +#endif + diff --git a/gpu/include/GrGpuD3D9.h b/gpu/include/GrGpuD3D9.h new file mode 100644 index 0000000000..c3d3e1a829 --- /dev/null +++ b/gpu/include/GrGpuD3D9.h @@ -0,0 +1,259 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGpuD3D9_DEFINED +#define GrGpuD3D9_DEFINED + +#include <Windows.h> +#include <d3d9.h> + +#include "GrGpu.h" + +class GrD3D9VertexBuffer; +class GrD3D9IndexBuffer; +class GrD3D9Texture; + +// For D3D9 GrRenderTarget casts to a (GrD3D9RenderTarget*) +struct GrD3D9RenderTarget { + IDirect3DSurface9* fColor; + IDirect3DSurface9* fStencil; + bool fClearStencil; +}; + +// GrGpu implementation for D3D9 fixed pipeline. +// Known needed improvements: +// vertex/index buffers need to be better managed: +// use no_overwrite and walk down VB/IB until reach end and wrap +// take advantage of the redrawHint and don't recopy vertex/idx data +// User created vertex buffers must have position Z values +// (required for fixed pipeline) but there is no way to communicate +// this now +// We create a temporary sysmem surface for each texture update. +// split this out into fixed/shader subclasses (use vdecls for shaders) +class GrGpuD3D9 : public GrGpu { +public: + GrGpuD3D9(IDirect3DDevice9* device); + virtual ~GrGpuD3D9(); + + // overrides from GrGpu + virtual GrTexture* createTexture(const TextureDesc& desc, + const void* srcData); + virtual GrVertexBuffer* createVertexBuffer(uint32_t size, bool dynamic); + virtual GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic); + + virtual void eraseColor(GrColor color); + virtual void eraseStencil(); + +protected: + // overrides from GrGpu + virtual bool flushGraphicsState(PrimitiveTypes type); + virtual void drawIndexArrayApi(PrimitiveTypes type, + int baseVertex, + int vertexCount, + int indexCount, + const uint16_t* indexArray, + bool redrawHint); + virtual void drawIndexBufferApi(PrimitiveTypes type, + int baseVertex, + int startIndex, + int vertexCount, + int indexCount, + GrIndexBuffer* indexBuffer, + bool redrawHint); + virtual void drawNonIndexedApi(PrimitiveTypes type, + int baseVertex, + int indexCount, + bool redrawHint); + virtual void flushScissor(); + +private: + + // baseVertex may be modified while setting up the stage + GrD3D9VertexBuffer* setupVBufferStage(int vsize, int* baseVertex, + int vertexCount, DrawModes mode); + GrD3D9IndexBuffer* setupIBufferStage(int* startIndex, int indexCount, + const uint16_t* indices); + static int vertexSize(int vertFlagBits, GrGpu::DrawModes mode); + static bool positionsOnly(int vertFlagBits); + + // notify callbacks to update state tracking when related + // objects are bound to the device or deleted outside of the class + void notifyVertexBufferBind(GrD3D9VertexBuffer* buffer); + void notifyVertexBufferDelete(GrD3D9VertexBuffer* buffer); + void notifyIndexBufferBind(GrD3D9IndexBuffer* buffer); + void notifyIndexBufferDelete(GrD3D9IndexBuffer* buffer); + void notifyTextureDelete(GrD3D9Texture* texture); + void notifyTextureRemoveRenderTarget(GrD3D9Texture* texture); + + IDirect3DSurface9* createStencil(uint32_t width, + uint32_t height, + D3DMULTISAMPLE_TYPE msType, + DWORD msQual); + + void setRenderTargetImm(); + + friend class GrD3D9VertexBuffer; + friend class GrD3D9IndexBuffer; + friend class GrD3D9Texture; + + GrIndexBuffer* fLastIndexBuffer; + + // used to track the COLORARG1 value for tex stage 0 + // needs to use ALPHAREPLICATE when using alpha-only textures + DWORD fLastColorArg1; + + IDirect3DDevice9* fDevice; + // We may use Ex functionality if this is a Ex device + IDirect3DDevice9Ex* fDeviceEx; + + enum VertDecls { + kInvalid_VertDecl = -1, + kPosOnly_VertDecl = 0, + kTex_VertDecl, + kColors_VertDecl, + kTexAndColors_VertDecl, + kPosAsTex_VertDecl, + kPosAsTexAndColors_VertDecl, + kVertDeclCount + }; + + static const VertDecls gVertFlags2VertDeclIdx[]; + static const DWORD gDeclToFVFs[]; + static const DWORD gTextFVF; + + DWORD fLastVertFVF; + + bool fLastBlendOff; + + // D3D allows user pointers in place of buffers for vertex/index data + // but it doesn't allow: + // -multiple streams (non-interleaved) ~ this will be resolved when we + // go AoS with our verts + // -mixing user pointer verts with index buffer (or vice versa) + // So we use these staging buffers + GrD3D9VertexBuffer* fStageVBuffer; + GrD3D9IndexBuffer* fStageIBuffer; + + // did we use texture coordinate generation at the last flush + bool fLastTexGen; + + GrD3D9RenderTarget fDefaultRenderTarget; + + // We use texture stage 0 to set a constant color + // D3D disables the stage if NULL is bound (even when the ops don't + // reference the texture). So we have a 1x1 dummy texture that + // gets set when drawing constant color with no texture + GrD3D9Texture* fDummyTexture; +}; + +class GrD3D9Texture : public GrTexture { +protected: + GrD3D9Texture(uint32_t width, + uint32_t height, + PixelConfig config, + IDirect3DTexture9* texture, + IDirect3DSurface9* stencil, + bool clearStencil, + GrGpuD3D9* gpuD3D9); +public: + virtual ~GrD3D9Texture(); + + // overloads of GrTexture + virtual void abandon(); + virtual bool isRenderTarget(); + virtual GrRenderTarget* asRenderTarget() + { return (GrRenderTarget*) &fRenderTarget; } + virtual void removeRenderTarget(); + virtual void uploadTextureData(uint32_t x, + uint32_t y, + uint32_t width, + uint32_t height, + const void* srcData); + IDirect3DTexture9* texture() const { return fTexture; } + IDirect3DSurface9* stencil() const { return fStencil; } + D3DFORMAT format() const { return fDesc.Format; } +private: + IDirect3DTexture9* fTexture; + GrD3D9RenderTarget fRenderTarget; + IDirect3DSurface9* fStencil; + D3DSURFACE_DESC fDesc; + GrGpuD3D9* fGpuD3D9; + + friend class GrGpuD3D9; + + typedef GrTexture INHERITED; +}; + +class GrD3D9VertexBuffer : public GrVertexBuffer { +protected: + GrD3D9VertexBuffer(uint32_t size, + bool dynamic, + IDirect3DVertexBuffer9* vbuffer, + GrGpuD3D9* gpuD3D9); +public: + virtual ~GrD3D9VertexBuffer(); + + IDirect3DVertexBuffer9* buffer() const { return fBuffer; } + + // overrides of GrVertexBuffer + virtual void abandon(); + virtual void* lock(); + virtual void unlock(); + virtual bool isLocked(); + virtual bool updateData(const void* src, uint32_t srcSizeInBytes); + +private: + IDirect3DVertexBuffer9* fBuffer; + D3DVERTEXBUFFER_DESC fDesc; + bool fLocked; + GrGpuD3D9* fGpuD3D9; + + friend class GrGpuD3D9; + + typedef GrVertexBuffer INHERITED; +}; + +class GrD3D9IndexBuffer : public GrIndexBuffer { +protected: + GrD3D9IndexBuffer(uint32_t size, + bool dynamic, + IDirect3DIndexBuffer9* vbuffer, + GrGpuD3D9* gpuD3D9); +public: + virtual ~GrD3D9IndexBuffer(); + + IDirect3DIndexBuffer9* buffer() const { return fBuffer; } + + // overrides of GrIndexBuffer + virtual void abandon(); + virtual void* lock(); + virtual void unlock(); + virtual bool isLocked(); + virtual bool updateData(const void* src, uint32_t srcSizeInBytes); +private: + IDirect3DIndexBuffer9* fBuffer; + D3DINDEXBUFFER_DESC fDesc; + bool fLocked; + GrGpuD3D9* fGpuD3D9; + + friend class GrGpuD3D9; + + typedef GrIndexBuffer INHERITED; +}; + +#endif + diff --git a/gpu/include/GrGpuVertex.h b/gpu/include/GrGpuVertex.h new file mode 100644 index 0000000000..1e3293a2ba --- /dev/null +++ b/gpu/include/GrGpuVertex.h @@ -0,0 +1,104 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGpuVertex_DEFINED +#define GrGpuVertex_DEFINED + +#include "GrGLConfig.h" +#include "GrPoint.h" + +#if GR_TEXT_SCALAR_IS_USHORT + typedef uint16_t GrTextScalar; + #define GrIntToTextScalar(x) ((uint16_t)x) + #define GrFixedToTextScalar(x) (x) +#elif GR_TEXT_SCALAR_IS_FIXED + typedef GrFixed GrTextScalar; + #define GrIntToTextScalar(x) GrIntToFixed(x) + #define GrFixedToTextScalar(x) (x) +#elif GR_TEXT_SCALAR_IS_FLOAT + typedef float GrTextScalar; + #define GrIntToTextScalar(x) ((GrTextScalar)x) + #define GrFixedToTextScalar(x) GrFixedToFloat(x) +#else + #error "Text scalar type not defined" +#endif + +// text has its own vertex class, since it may want to be in fixed point (given) +// that it starts with all integers) even when the default vertices are floats +struct GrGpuTextVertex { + GrTextScalar fX; + GrTextScalar fY; + + void set(GrTextScalar x, GrTextScalar y) { + fX = x; + fY = y; + } + + void setI(int x, int y) { + fX = GrIntToTextScalar(x); + fY = GrIntToTextScalar(y); + } + + void setX(GrFixed x, GrFixed y) { + fX = GrFixedToTextScalar(x); + fY = GrFixedToTextScalar(y); + } + + // rect fan is counter-clockwise + + void setRectFan(GrTextScalar l, GrTextScalar t, GrTextScalar r, + GrTextScalar b) { + GrGpuTextVertex* v = this; + v[0].set(l, t); + v[1].set(l, b); + v[2].set(r, b); + v[3].set(r, t); + } + + void setIRectFan(int l, int t, int r, int b) { + this->setRectFan(GrIntToTextScalar(l), GrIntToTextScalar(t), + GrIntToTextScalar(r), GrIntToTextScalar(b)); + } + + void setIRectFan(int l, int t, int r, int b, size_t stride) { + GrAssert(stride > sizeof(GrGpuTextVertex)); + char* v = (char*)this; + ((GrGpuTextVertex*)(v + 0*stride))->setI(l, t); + ((GrGpuTextVertex*)(v + 1*stride))->setI(l, b); + ((GrGpuTextVertex*)(v + 2*stride))->setI(r, b); + ((GrGpuTextVertex*)(v + 3*stride))->setI(r, t); + } + + // counter-clockwise fan + void setXRectFan(GrFixed l, GrFixed t, GrFixed r, GrFixed b) { + this->setRectFan(GrFixedToTextScalar(l), GrFixedToTextScalar(t), + GrFixedToTextScalar(r), GrFixedToTextScalar(b)); + } + + void setXRectFan(GrFixed l, GrFixed t, GrFixed r, GrFixed b, size_t stride) { + GrAssert(stride > sizeof(GrGpuTextVertex)); + char* v = (char*)this; + ((GrGpuTextVertex*)(v + 0*stride))->setX(l, t); + ((GrGpuTextVertex*)(v + 1*stride))->setX(l, b); + ((GrGpuTextVertex*)(v + 2*stride))->setX(r, b); + ((GrGpuTextVertex*)(v + 3*stride))->setX(r, t); + } + +}; + +#endif + diff --git a/gpu/include/GrIPoint.h b/gpu/include/GrIPoint.h new file mode 100644 index 0000000000..b979a09340 --- /dev/null +++ b/gpu/include/GrIPoint.h @@ -0,0 +1,35 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrIPoint_DEFINED +#define GrIPoint_DEFINED + +#include "GrTypes.h" + +struct GrIPoint { +public: + int32_t fX, fY; + + GrIPoint(int32_t x, int32_t y) : fX(x), fY(y) {} + + void set(int32_t x, int32_t y) { + fX = x; + fY = y; + } +}; + +#endif diff --git a/gpu/include/GrInOrderDrawBuffer.h b/gpu/include/GrInOrderDrawBuffer.h new file mode 100644 index 0000000000..805861ada1 --- /dev/null +++ b/gpu/include/GrInOrderDrawBuffer.h @@ -0,0 +1,131 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrInOrderDrawBuffer_DEFINED +#define GrInOrderDrawBuffer_DEFINED + +#include "GrDrawTarget.h" +#include "GrAllocPool.h" +#include "GrAllocator.h" +#include "GrClip.h" + +class GrVertexBufferAllocPool; + +// TODO: don't save clip per draw +class GrInOrderDrawBuffer : public GrDrawTarget { +public: + + GrInOrderDrawBuffer(GrVertexBufferAllocPool* pool = NULL); + + virtual ~GrInOrderDrawBuffer(); + + void initializeDrawStateAndClip(const GrDrawTarget& target); + + virtual void drawIndexed(PrimitiveType type, + uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount); + + virtual void drawNonIndexed(PrimitiveType type, + uint32_t startVertex, + uint32_t vertexCount); + + virtual bool geometryHints(GrVertexLayout vertexLayout, + int32_t* vertexCount, + int32_t* indexCount) const; + + void reset(); + + void playback(GrDrawTarget* target); + +private: + + struct Draw { + PrimitiveType fType; + uint32_t fStartVertex; + uint32_t fStartIndex; + uint32_t fVertexCount; + uint32_t fIndexCount; + bool fStateChange; + GrVertexLayout fVertexLayout; + bool fUseVertexBuffer; + bool fClipChanged; + union { + const GrVertexBuffer* fVertexBuffer; + const void* fVertexArray; + }; + bool fUseIndexBuffer; + union { + const GrIndexBuffer* fIndexBuffer; + const void* fIndexArray; + }; + }; + + virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout, + void** vertices, + void** indices); + virtual void releaseGeometryHelper(); + virtual void clipWillChange(const GrClip& clip); + + + bool grabState(); + bool grabClip(); + + GrTAllocator<Draw> fDraws; + // HACK: We hold refs on textures in saved state but not RTs, VBs, and IBs. + // a) RTs aren't ref counted (yet) + // b) we are only using this class for text which doesn't use VBs or IBs + // This should be fixed by either refcounting them all or having some + // notification occur if a cache is purging an object we have a ptr to. + GrTAllocator<SavedDrawState> fStates; + + GrTAllocator<GrClip> fClips; + bool fClipChanged; + + // vertices are either queued in cpu arrays or some vertex buffer pool + // that knows about a specific GrGpu object. + GrAllocPool fCPUVertices; + GrVertexBufferAllocPool* fBufferVertices; + GrAllocPool fIndices; + void* fCurrReservedVertices; + void* fCurrReservedIndices; + // valid if we're queueing vertices in fBufferVertices + GrVertexBuffer* fCurrVertexBuffer; + uint32_t fCurrStartVertex; + + // caller may conservatively over allocate vertices / indices. + // we release unused space back to allocator if possible + size_t fReservedVertexBytes; + size_t fReservedIndexBytes; + size_t fUsedReservedVertexBytes; + size_t fUsedReservedIndexBytes; + + static const uint32_t STATES_BLOCK_SIZE = 8; + static const uint32_t DRAWS_BLOCK_SIZE = 8; + static const uint32_t CLIPS_BLOCK_SIZE = 8; + static const uint32_t VERTEX_BLOCK_SIZE = 1 << 12; + static const uint32_t INDEX_BLOCK_SIZE = 1 << 10; + int8_t fDrawsStorage[sizeof(Draw) * + DRAWS_BLOCK_SIZE]; + int8_t fStatesStorage[sizeof(SavedDrawState) * + STATES_BLOCK_SIZE]; + int8_t fClipsStorage[sizeof(GrClip) * + CLIPS_BLOCK_SIZE]; +}; + +#endif diff --git a/gpu/include/GrIndexBuffer.h b/gpu/include/GrIndexBuffer.h new file mode 100644 index 0000000000..0f4c4d691f --- /dev/null +++ b/gpu/include/GrIndexBuffer.h @@ -0,0 +1,92 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrIndexBuffer_DEFINED +#define GrIndexBuffer_DEFINED + +#include "GrRefCnt.h" + +class GrIndexBuffer : public GrRefCnt { +protected: + GrIndexBuffer(uint32_t sizeInBytes, bool dynamic) : + fSizeInBytes(sizeInBytes), + fDynamic(dynamic) {} +public: + virtual ~GrIndexBuffer() {} + + /** + Retrieves the size of the index buffer + + @return the size of the index buffer in bytes + */ + uint32_t size() const { return fSizeInBytes; } + + /** + Retrieves whether the index buffer was created with the dynamic flag + + @return true if the index buffer was created with the dynamic flag + */ + bool dynamic() const { return fDynamic; } + + /** + Indicates that GPU context in which this veretx buffer was created is + destroyed and that Ganesh should not attempt to free the texture with the + underlying API. + */ + virtual void abandon() = 0; + + /** + Locks the index buffer to be written by the CPU. + + The previous content of the index buffer is invalidated. It is an error to + draw whil the buffer is locked. It is an error to call lock on an already + locked index buffer. + + @return a pointer to the index data or NULL if the lock fails. + */ + virtual void* lock() = 0; + + /** + Unlocks the index buffer. + + The pointer returned by the previous lock call will no longer be valid. + */ + virtual void unlock() = 0; + + /** + Queries whether the index buffer has been locked. + + @return true if the index buffer is locked, false otherwise. + */ + virtual bool isLocked() const = 0; + + /** + Updates the index buffer data. + + The size of the index buffer will be preserved. However, only the updated + region will have defined contents. + + @return returns true if the update succeeds, false otherwise. + */ + virtual bool updateData(const void* src, uint32_t srcSizeInBytes) = 0; + +private: + uint32_t fSizeInBytes; + bool fDynamic; +}; + +#endif diff --git a/gpu/include/GrInstanceCounter.h b/gpu/include/GrInstanceCounter.h new file mode 100644 index 0000000000..11cec2b2ec --- /dev/null +++ b/gpu/include/GrInstanceCounter.h @@ -0,0 +1,47 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrInstanceCounter_DEFINED +#define GrInstanceCounter_DEFINED + +#include "GrTypes.h" + +template <typename T> class GrInstanceCounter { +public: + GrInstanceCounter() { + ++gCounter; + GrPrintf("+ %s %d\n", T::InstanceCounterClassName(), gCounter); + } + + ~GrInstanceCounter() { + --gCounter; + GrPrintf("- %s %d\n", T::InstanceCounterClassName(), gCounter); + } + +private: + static int gCounter; +}; + +template <typename T> int GrInstanceCounter<T>::gCounter; + +#define DECLARE_INSTANCE_COUNTER(T) \ + static const char* InstanceCounterClassName() { return #T; } \ + friend class GrInstanceCounter<T>; \ + GrInstanceCounter<T> fInstanceCounter + +#endif + diff --git a/gpu/include/GrKey.h b/gpu/include/GrKey.h new file mode 100644 index 0000000000..19133aee7a --- /dev/null +++ b/gpu/include/GrKey.h @@ -0,0 +1,47 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrKey_DEFINED +#define GrKey_DEFINED + +#include "GrRefCnt.h" + +class GrKey : public GrRefCnt { +public: + typedef intptr_t Hash; + + explicit GrKey(Hash hash) : fHash(hash) {} + + intptr_t getHash() const { return fHash; } + + bool operator<(const GrKey& rh) const { + return fHash < rh.fHash || (fHash == rh.fHash && this->lt(rh)); + } + bool operator==(const GrKey& rh) const { + return fHash == rh.fHash && this->eq(rh); + } + +protected: + virtual bool lt(const GrKey& rh) const = 0; + virtual bool eq(const GrKey& rh) const = 0; + +private: + const Hash fHash; +}; + +#endif + diff --git a/gpu/include/GrMatrix.h b/gpu/include/GrMatrix.h new file mode 100644 index 0000000000..43fd4a5ed1 --- /dev/null +++ b/gpu/include/GrMatrix.h @@ -0,0 +1,370 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +
+#ifndef GrMatrix_DEFINED
+#define GrMatrix_DEFINED
+
+#include "GrPoint.h"
+
+struct GrRect;
+
+/*
+ * 3x3 matrix
+ */
+class GrMatrix {
+public:
+ static const GrMatrix& I();
+ static const GrScalar gRESCALE;
+ /**
+ * Handy index constants
+ */
+ enum {
+ kScaleX,
+ kSkewX,
+ kTransX,
+ kSkewY,
+ kScaleY,
+ kTransY,
+ kPersp0,
+ kPersp1,
+ kPersp2
+ };
+
+ /**
+ * Create an uninitialized matrix
+ */
+ GrMatrix() {
+ fTypeMask = 0;
+ }
+
+ /**
+ * Create a matrix from an array of values
+ * @param values row-major array of matrix components
+ */
+ explicit GrMatrix(GrScalar* values) {
+ setToArray(values);
+ }
+
+ /**
+ * Create a matrix from values
+ * @param scaleX (0,0) matrix element
+ * @param skewX (0,1) matrix element
+ * @param transX (0,2) matrix element
+ * @param skewY (1,0) matrix element
+ * @param scaleY (1,1) matrix element
+ * @param transY (1,2) matrix element
+ * @param persp0 (2,0) matrix element
+ * @param persp1 (2,1) matrix element
+ * @param persp2 (2,2) matrix element
+ */
+ GrMatrix(GrScalar scaleX,
+ GrScalar skewX,
+ GrScalar transX,
+ GrScalar skewY,
+ GrScalar scaleY,
+ GrScalar transY,
+ GrScalar persp0,
+ GrScalar persp1,
+ GrScalar persp2) {
+ setAll(scaleX, skewX, transX,
+ skewY, scaleY, transY,
+ persp0, persp1, persp2);
+ }
+
+ /**
+ * access matrix component
+ * @return matrix component value
+ */
+ const GrScalar& operator[] (int idx) const {
+ GrAssert((unsigned)idx < 9);
+ return fM[idx];
+ }
+
+ /**
+ * Set a matrix from an array of values
+ * @param values row-major array of matrix components
+ */
+ void setToArray(GrScalar* values) {
+ for (int i = 0; i < 9; ++i) {
+ fM[i] = values[i];
+ }
+ setTypeMask();
+ }
+
+ /**
+ * Create a matrix from values
+ * @param scaleX (0,0) matrix element
+ * @param skewX (0,1) matrix element
+ * @param transX (0,2) matrix element
+ * @param skewY (1,0) matrix element
+ * @param scaleY (1,1) matrix element
+ * @param transY (1,2) matrix element
+ * @param persp0 (2,0) matrix element
+ * @param persp1 (2,1) matrix element
+ * @param persp2 (2,2) matrix element
+ */
+ void setAll(GrScalar scaleX,
+ GrScalar skewX,
+ GrScalar transX,
+ GrScalar skewY,
+ GrScalar scaleY,
+ GrScalar transY,
+ GrScalar persp0,
+ GrScalar persp1,
+ GrScalar persp2) {
+ fM[kScaleX] = scaleX;
+ fM[kSkewX] = skewX;
+ fM[kTransX] = transX;
+ fM[kSkewY] = skewY;
+ fM[kScaleY] = scaleY;
+ fM[kTransY] = transY;
+ fM[kPersp0] = persp0;
+ fM[kPersp1] = persp1;
+ fM[kPersp2] = persp2;
+
+ setTypeMask();
+ }
+
+ /**
+ * set matrix component
+ * @param idx index of component to set
+ * @param value value to set component to
+ */
+ inline void set(int idx, GrScalar value);
+
+ /**
+ * make this matrix an identity matrix
+ */
+ void setIdentity();
+
+ /**
+ * overwrite entire matrix to be a translation matrix
+ * @param dx amount to translate by in x
+ * @param dy amount to translate by in y
+ */
+ void setTranslate(GrScalar dx, GrScalar dy);
+
+ /**
+ * overwrite entire matrix to be a scaling matrix
+ * @param sx x scale factor
+ * @param sy y scale factor
+ */
+ void setScale(GrScalar sx, GrScalar sy);
+
+ /**
+ * overwrite entire matrix to be a skew matrix
+ * @param skx x skew factor
+ * @param sky y skew factor
+ */
+ void setSkew(GrScalar skx, GrScalar sky);
+
+ /**
+ * set this matrix to be a concantenation of two
+ * matrices (a*b). Either a, b, or both can be this matrix.
+ * @param a first matrix to multiply
+ * @param b second matrix to multiply
+ */
+ void setConcat(const GrMatrix& a, const GrMatrix& b);
+
+ /**
+ * Set this matrix to this*m
+ * @param m matrix to concatenate
+ */
+ void preConcat(const GrMatrix& m);
+
+ /**
+ * Set this matrix to m*this
+ * @param m matrix to concatenate
+ */
+ void postConcat(const GrMatrix& m);
+
+ /**
+ * Compute the inverse of this matrix, and return true if it is invertible,
+ * or false if not.
+ *
+ * If inverted is not null, and the matrix is invertible, then the inverse
+ * is written into it. If the matrix is not invertible (this method returns
+ * false) then inverted is left unchanged.
+ */
+ bool invert(GrMatrix* inverted) const;
+
+ /**
+ * Transforms a point by the matrix
+ *
+ * @param src the point to transform
+ * @return the transformed point
+ */
+ GrPoint mapPoint(const GrPoint& src) const {
+ GrPoint result;
+ (this->*gMapProcs[fTypeMask])(&result, &src, 1);
+ return result;
+ }
+
+ /**
+ * Transforms an array of points by the matrix.
+ *
+ * @param dstPts the array to write transformed points into
+ * @param srcPts the array of points to transform
+ @ @param count the number of points to transform
+ */
+ void mapPoints(GrPoint dstPts[],
+ const GrPoint srcPts[],
+ uint32_t count) const {
+ (this->*gMapProcs[fTypeMask])(dstPts, srcPts, count);
+ }
+
+ /**
+ * Transforms pts with arbitrary stride in place.
+ *
+ * @param start pointer to first point to transform
+ * @param stride distance in bytes between consecutive points
+ @ @param count the number of points to transform
+ */
+ void mapPointsWithStride(GrPoint* start,
+ size_t stride,
+ uint32_t count) const {
+ for (uint32_t i = 0; i < count; ++i) {
+ this->mapPoints(start, start, 1);
+ start = (GrPoint*)((intptr_t)start + stride);
+ }
+ }
+
+ /**
+ * Transform the 4 corners of the src rect, and return the bounding rect
+ * in the dst rect. Note: src and dst may point to the same memory.
+ */
+ void mapRect(GrRect* dst, const GrRect& src) const;
+
+ /**
+ * Transform the 4 corners of the rect, and return their bounds in the rect
+ */
+ void mapRect(GrRect* rect) const {
+ this->mapRect(rect, *rect);
+ }
+
+ /**
+ * Checks if matrix is a perspective matrix.
+ * @return true if third row is not (0, 0, 1)
+ */
+ bool hasPerspective() const;
+
+ /**
+ * Checks whether matrix is identity
+ * @return true if matrix is idenity
+ */
+ bool isIdentity() const;
+
+ /**
+ * Calculates the maximum stretching factor of the matrix. Only defined if
+ * the matrix does not have perspective.
+ *
+ * @return maximum strecthing factor or negative if matrix has perspective.
+ */
+ GrScalar getMaxStretch() const;
+
+ /**
+ * Checks for matrix equality. Test is element-by-element equality,
+ * not a homogeneous test.
+ * @return true if matrices are equal, false otherwise
+ */
+ bool operator == (const GrMatrix& m) const;
+
+ /**
+ * Checks for matrix inequality. Test is element-by-element inequality,
+ * not a homogeneous test.
+ * @return true if matrices are not equal, false otherwise
+ */
+ bool operator != (const GrMatrix& m) const;
+
+ static void UnitTest();
+
+private:
+
+ void setTypeMask();
+
+ double determinant() const;
+
+ enum TypeBits {
+ kScale_TypeBit = 1 << 0, // set if scales are not both 1
+ kTranslate_TypeBit = 1 << 1, // set if translates are not both 0
+ kSkew_TypeBit = 1 << 2, // set if skews are not both 0
+ kPerspective_TypeBit = 1 << 3, // set if perspective
+ kZeroScale_TypeBit = 1 << 4, // set if scales are both zero
+ };
+
+ void mapIdentity(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapScale(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapScaleAndSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapSkewAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapNonPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapZero(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapSetToTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapSwappedScale(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ void mapSwappedScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+
+ void mapInvalid(GrPoint* dst, const GrPoint* src, uint32_t count) const;
+
+ typedef void (GrMatrix::*MapProc) (GrPoint* dst, const GrPoint* src, uint32_t count) const;
+ static const MapProc gMapProcs[];
+
+ int fTypeMask;
+
+ GrScalar fM[9];
+};
+
+void GrMatrix::set(int idx, GrScalar value) {
+ GrAssert((unsigned)idx < 9);
+ fM[idx] = value;
+ if (idx > 5) {
+ if (0 != fM[kPersp0] || 0 != fM[kPersp1] ||
+ gRESCALE != fM[kPersp2]) {
+ fTypeMask |= kPerspective_TypeBit;
+ } else {
+ fTypeMask &= ~kPerspective_TypeBit;
+ }
+ } else if (!(idx % 4)) {
+ if ((GR_Scalar1 == fM[kScaleX] && GR_Scalar1 == fM[kScaleY])) {
+ fTypeMask &= ~kScale_TypeBit;
+ fTypeMask &= ~kZeroScale_TypeBit;
+ } else {
+ fTypeMask |= kScale_TypeBit;
+ if ((0 == fM[kScaleX] && 0 == fM[kScaleY])) {
+ fTypeMask |= kZeroScale_TypeBit;
+ } else {
+ fTypeMask &= ~kZeroScale_TypeBit;
+ }
+ }
+ } else if (2 == (idx % 3)) {
+ if (0 != fM[kTransX] || 0 != fM[kTransY]) {
+ fTypeMask |= kTranslate_TypeBit;
+ } else {
+ fTypeMask &= ~kTranslate_TypeBit;
+ }
+ } else {
+ if (0 != fM[kSkewX] || 0 != fM[kSkewY]) {
+ fTypeMask |= kSkew_TypeBit;
+ } else {
+ fTypeMask &= ~kSkew_TypeBit;
+ }
+ }
+}
+
+#endif diff --git a/gpu/include/GrMemory.h b/gpu/include/GrMemory.h new file mode 100644 index 0000000000..673d0ab43d --- /dev/null +++ b/gpu/include/GrMemory.h @@ -0,0 +1,151 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrMemory_DEFINED +#define GrMemory_DEFINED + +#include "GrNoncopyable.h" + +class GrAutoMalloc : GrNoncopyable { +public: + GrAutoMalloc(size_t bytes) : fPtr(GrMalloc(bytes)) {} + ~GrAutoMalloc() { GrFree(fPtr); } + + /** + * Return the allocated memory, or NULL if it has already been freed or + * detached. + */ + void* get() const { return fPtr; } + + /** + * transfer ownership of the memory to the caller. It must be freed with + * a call to GrFree() + */ + void* detach() { + void* ptr = fPtr; + fPtr = NULL; // we no longer own the block + return ptr; + } + + /** + * free the block now. get() will now return NULL + */ + void free() { + GrFree(fPtr); + fPtr = NULL; + } + +private: + void* fPtr; +}; + +/** + * Variant of GrAutoMalloc with a compile-time specified byte size that is + * pre-allocated in the class object, avoiding a call to to GrMalloc if + * possible. + */ +template <size_t SIZE> class GrAutoSMalloc : GrNoncopyable { +public: + GrAutoSMalloc() { + fPtr = fStorage; + fAllocatedBytes = SIZE; + } + + explicit GrAutoSMalloc(size_t bytes) { + if (bytes > SIZE) { + fPtr = GrMalloc(bytes); + fAllocatedBytes = bytes; + } else { + fPtr = fStorage; + fAllocatedBytes = SIZE; + } + } + + ~GrAutoSMalloc() { + if (fPtr != (void*)fStorage) { + GrFree(fPtr); + } + } + + /** + * Return the allocated memory, or NULL if it has already been freed or + * detached. + */ + void* get() const { return fPtr; } + + /** + * Reallocates to a new size. May or may not call malloc. The contents + * are not preserved. If growOnly is true it will never reduce the + * allocated size. + */ + void* realloc(size_t newSize, bool growOnly = false) { + if (newSize <= SIZE) { + if (NULL == fPtr) { + fPtr = fStorage; + fAllocatedBytes = SIZE; + } else if (!growOnly && fPtr != (void*)fStorage) { + GrFree(fPtr); + fPtr = fStorage; + fAllocatedBytes = SIZE; + } + } else if ((newSize > fAllocatedBytes) || + (!growOnly && newSize < (fAllocatedBytes >> 1))) { + if (NULL != fPtr && fPtr != (void*)fStorage) { + GrFree(fPtr); + } + fPtr = GrMalloc(newSize); + fAllocatedBytes = newSize; + } + GrAssert(fAllocatedBytes >= newSize); + GrAssert((fPtr == fStorage) == (fAllocatedBytes == SIZE)); + GR_DEBUGCODE(memset(fPtr, 0xEF, fAllocatedBytes)); + return fPtr; + } + + /** + * free the block now. get() will now return NULL + */ + void free() { + if (fPtr != (void*)fStorage) { + GrFree(fPtr); + } + fAllocatedBytes = 0; + fPtr = NULL; + } + +private: + void* fPtr; + uint32_t fAllocatedBytes; + uint32_t fStorage[GrALIGN4(SIZE) >> 2]; +}; + +/** + * Variant of GrAutoMalloc with a compile-time specified byte size that is + * pre-allocated in the class object, avoiding a call to to GrMalloc if + * possible. + */ +template <int COUNT, typename T> +class GrAutoSTMalloc : public GrAutoSMalloc<COUNT * sizeof(T)> { +public: + GrAutoSTMalloc(int count) : GrAutoSMalloc<COUNT * sizeof(T)>(count * sizeof(T)) {} + + operator T*() { return (T*)this->get(); } +}; + + +#endif + diff --git a/gpu/include/GrMesh.h b/gpu/include/GrMesh.h new file mode 100644 index 0000000000..4d904e41bd --- /dev/null +++ b/gpu/include/GrMesh.h @@ -0,0 +1,42 @@ +#ifndef GrMesh_DEFINED +#define GrMesh_DEFINED + +#include "SkRect.h" +#include "SkPoint.h" + +class SkCanvas; +class SkPaint; + +class GrMesh { +public: + GrMesh(); + ~GrMesh(); + + GrMesh& operator=(const GrMesh& src); + + void init(const SkRect& bounds, int rows, int cols, + const SkRect& texture); + + const SkRect& bounds() const { return fBounds; } + + int rows() const { return fRows; } + int cols() const { return fCols; } + SkPoint& pt(int row, int col) { + return fPts[row * (fRows + 1) + col]; + } + + void draw(SkCanvas*, const SkPaint&); + void drawWireframe(SkCanvas* canvas, const SkPaint& paint); + +private: + SkRect fBounds; + int fRows, fCols; + SkPoint* fPts; + SkPoint* fTex; // just points into fPts, not separately allocated + int fCount; + uint16_t* fIndices; + int fIndexCount; +}; + +#endif + diff --git a/gpu/include/GrNoncopyable.h b/gpu/include/GrNoncopyable.h new file mode 100644 index 0000000000..888e3b173b --- /dev/null +++ b/gpu/include/GrNoncopyable.h @@ -0,0 +1,38 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrNoncopyable_DEFINED +#define GrNoncopyable_DEFINED + +#include "GrTypes.h" + +/** + * Base for classes that want to disallow copying themselves. It makes its + * copy-constructor and assignment operators private (and unimplemented). + */ +class GrNoncopyable { +public: + GrNoncopyable() {} + +private: + // illegal + GrNoncopyable(const GrNoncopyable&); + GrNoncopyable& operator=(const GrNoncopyable&); +}; + +#endif + diff --git a/gpu/include/GrPath.h b/gpu/include/GrPath.h new file mode 100644 index 0000000000..a9b75665c3 --- /dev/null +++ b/gpu/include/GrPath.h @@ -0,0 +1,84 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrPath_DEFINED +#define GrPath_DEFINED + +#include "GrPathSink.h" +#include "GrPathIter.h" +#include "GrTDArray.h" +#include "GrPoint.h" + +class GrPath : public GrPathSink { +public: + GrPath(); + GrPath(const GrPath&); + explicit GrPath(GrPathIter&); + virtual ~GrPath(); + + GrPathIter::ConvexHint getConvexHint() const { return fConvexHint; } + void setConvexHint(GrPathIter::ConvexHint hint) { fConvexHint = hint; } + + void resetFromIter(GrPathIter*); + + // overrides from GrPathSink + + virtual void moveTo(GrScalar x, GrScalar y); + virtual void lineTo(GrScalar x, GrScalar y); + virtual void quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1); + virtual void cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1, + GrScalar x2, GrScalar y2); + virtual void close(); + + class Iter : public GrPathIter { + public: + Iter(const GrPath& path); + + // overrides from GrPathIter + virtual Command next(GrPoint points[]); + virtual ConvexHint hint() const; + virtual Command next(); + virtual void rewind(); + private: + const GrPath& fPath; + GrPoint fLastPt; + int fVerbIndex; + int fPtIndex; + }; + +private: + enum Verb { + kMove, kLine, kQuad, kCubic, kClose + }; + + GrTDArray<uint8_t> fVerbs; + GrTDArray<GrPoint> fPts; + GrPathIter::ConvexHint fConvexHint; + + // this ensures we have a moveTo at the start of each contour + inline void ensureMoveTo(); + + bool wasLastVerb(Verb verb) const { + int count = fVerbs.count(); + return count > 0 && verb == fVerbs[count - 1]; + } + + friend class Iter; +}; + +#endif + diff --git a/gpu/include/GrPathIter.h b/gpu/include/GrPathIter.h new file mode 100644 index 0000000000..028faaa14d --- /dev/null +++ b/gpu/include/GrPathIter.h @@ -0,0 +1,110 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrPathIter_DEFINED +#define GrPathIter_DEFINED + +#include "GrTypes.h" + +struct GrPoint; + +/** + 2D Path iterator. Porting layer creates a subclass of this. It allows Ganesh to + parse the top-level API's 2D paths. Supports lines, quadratics, and cubic + pieces and moves (multi-part paths). + */ +class GrPathIter { +public: + /** + Returned by next(). Indicates the next piece of the path. + */ + enum Command { + kMove_Command, //!< next() returns 1 pt + // Starts a new subpath at + // at the returned point + kLine_Command, //!< next() returns 2 pts + // Adds a line segment + kQuadratic_Command, //!< next() returns 3 pts + // Adds a quadratic segment + kCubic_Command, //!< next() returns 4 pts + // Adds a cubic segment + kClose_Command, //!< next() returns 0 pts + kEnd_Command //!< next() returns 0 pts + // Implictly closes the last + // point + }; + + enum ConvexHint { + kNone_ConvexHint, //<! No hint about convexity + // of the path + kConvex_ConvexHint, //<! Path is one convex piece + kNonOverlappingConvexPieces_ConvexHint, //<! Multiple convex pieces, + // pieces are known to be + // disjoint + kSameWindingConvexPieces_ConvexHint, //<! Multiple convex pieces, + // may or may not intersect, + // either all wind cw or all + // wind ccw. + kConcave_ConvexHint //<! Path is known to be + // concave + }; + + static int NumCommandPoints(Command cmd) { + static const int numPoints[] = { + 1, 2, 3, 4, 0, 0 + }; + return numPoints[cmd]; + } + + virtual ~GrPathIter() {}; + + /** + Iterates through the path. Should not be called after + kEnd_Command has been returned once. This version retrieves the + points for the command. + @param points The points relevant to returned commend. See Command + enum for number of points valid for each command. + @return The next command of the path. + */ + virtual Command next(GrPoint points[4]) = 0; + + /** + * If the host API has knowledge of the convexity of the path + * it can be communicated by this hint. Ganesh can make these + * determinations itself. So it is not necessary to compute + * convexity status if it isn't already determined. + * + * @return a hint about the convexity of the path. + */ + virtual ConvexHint hint() const { return kNone_ConvexHint; } + + /** + Iterates through the path. Should not be called after + kEnd_Command has been returned once. This version does not retrieve the + points for the command. + @return The next command of the path. + */ + virtual Command next() = 0; + + /** + Restarts iteration from the beginning. + */ + virtual void rewind() = 0; + +}; + +#endif diff --git a/gpu/include/GrPathSink.h b/gpu/include/GrPathSink.h new file mode 100644 index 0000000000..4e8a0c2c43 --- /dev/null +++ b/gpu/include/GrPathSink.h @@ -0,0 +1,36 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrPathSink_DEFINED +#define GrPathSink_DEFINED + +#include "GrScalar.h" + +class GrPathSink { +public: + virtual ~GrPathSink() {} + + virtual void moveTo(GrScalar x, GrScalar y) = 0; + virtual void lineTo(GrScalar x, GrScalar y) = 0; + virtual void quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1) = 0; + virtual void cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1, + GrScalar x2, GrScalar y2) = 0; + virtual void close() = 0; +}; + +#endif + diff --git a/gpu/include/GrPlotMgr.h b/gpu/include/GrPlotMgr.h new file mode 100644 index 0000000000..cd60bdebde --- /dev/null +++ b/gpu/include/GrPlotMgr.h @@ -0,0 +1,84 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrPlotMgr_DEFINED +#define GrPlotMgr_DEFINED + +#include "GrTypes.h" +#include "GrPoint.h" + +class GrPlotMgr : GrNoncopyable { +public: + GrPlotMgr(int width, int height) { + fDim.set(width, height); + size_t needed = width * height; + if (needed <= sizeof(fStorage)) { + fBusy = fStorage; + } else { + fBusy = new char[needed]; + } + this->reset(); + } + + ~GrPlotMgr() { + if (fBusy != fStorage) { + delete[] fBusy; + } + } + + void reset() { + Gr_bzero(fBusy, fDim.fX * fDim.fY); + } + + bool newPlot(GrIPoint16* loc) { + char* busy = fBusy; + for (int y = 0; y < fDim.fY; y++) { + for (int x = 0; x < fDim.fX; x++) { + if (!*busy) { + *busy = true; + loc->set(x, y); + return true; + } + busy++; + } + } + return false; + } + + bool isBusy(int x, int y) const { + GrAssert((unsigned)x < (unsigned)fDim.fX); + GrAssert((unsigned)y < (unsigned)fDim.fY); + return fBusy[y * fDim.fX + x] != 0; + } + + void freePlot(int x, int y) { + GrAssert((unsigned)x < (unsigned)fDim.fX); + GrAssert((unsigned)y < (unsigned)fDim.fY); + fBusy[y * fDim.fX + x] = false; + } + +private: + enum { + STORAGE = 64 + }; + char fStorage[STORAGE]; + char* fBusy; + GrIPoint16 fDim; +}; + +#endif + diff --git a/gpu/include/GrPoint.h b/gpu/include/GrPoint.h new file mode 100644 index 0000000000..bb24959c34 --- /dev/null +++ b/gpu/include/GrPoint.h @@ -0,0 +1,287 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrPoint_DEFINED +#define GrPoint_DEFINED + +#include "GrTypes.h" +#include "GrScalar.h" + +/** + * 2D Point struct + */ +struct GrPoint { +public: + GrScalar fX, fY; + + GrPoint() {} + GrPoint(GrScalar x, GrScalar y) { fX = x; fY = y; } + + GrScalar x() const { return fX; } + GrScalar y() const { return fY; } + + void set(GrScalar x, GrScalar y) { + fX = x; + fY = y; + } + + void setAsMidPoint(const GrPoint& a, const GrPoint& b) { + fX = GrScalarAve(a.fX, b.fX); + fY = GrScalarAve(a.fY, b.fY); + } + + void offset(GrScalar dx, GrScalar dy) { + fX += dx; + fY += dy; + } + + GrScalar distanceToSqd(const GrPoint& p) const { + GrScalar dx = (p.fX - fX); + GrScalar dy = (p.fY - fY); + return GrMul(dx, dx) + GrMul(dy, dy); + } + + GrScalar distanceTo(const GrPoint& p) const { + // TODO: fixed point sqrt + return GrFloatToScalar(sqrtf(GrScalarToFloat(distanceToSqd(p)))); + } + + GrScalar distanceToOriginSqd() const { + return GrMul(fX, fX) + GrMul(fY, fY); + } + + GrScalar distanceToOrigin() const { + return GrFloatToScalar(sqrtf(GrScalarToFloat(distanceToOriginSqd()))); + } + + inline GrScalar distanceToLineBetweenSqd(const GrPoint& a, + const GrPoint& b) const; + + inline GrScalar distanceToLineBetween(const GrPoint& a, + const GrPoint& b) const; + + inline GrScalar distanceToLineSegmentBetweenSqd(const GrPoint& a, + const GrPoint& b) const; + + inline GrScalar distanceToLineSegmentBetween(const GrPoint& a, + const GrPoint& b) const; + + // counter-clockwise fan + void setRectFan(GrScalar l, GrScalar t, GrScalar r, GrScalar b) { + GrPoint* v = this; + v[0].set(l, t); + v[1].set(l, b); + v[2].set(r, b); + v[3].set(r, t); + } + + void setRectFan(GrScalar l, GrScalar t, GrScalar r, GrScalar b, size_t stride) { + GrAssert(stride >= sizeof(GrPoint)); + ((GrPoint*)((intptr_t)this + 0 * stride))->set(l, t); + ((GrPoint*)((intptr_t)this + 1 * stride))->set(l, b); + ((GrPoint*)((intptr_t)this + 2 * stride))->set(r, b); + ((GrPoint*)((intptr_t)this + 3 * stride))->set(r, t); + } + + // counter-clockwise fan + void setIRectFan(int l, int t, int r, int b) { + GrPoint* v = this; + v[0].set(GrIntToScalar(l), GrIntToScalar(t)); + v[1].set(GrIntToScalar(l), GrIntToScalar(b)); + v[2].set(GrIntToScalar(r), GrIntToScalar(b)); + v[3].set(GrIntToScalar(r), GrIntToScalar(t)); + } + + void setIRectFan(int l, int t, int r, int b, size_t stride) { + GrAssert(stride >= sizeof(GrPoint)); + ((GrPoint*)((intptr_t)this + 0 * stride))->set(GrIntToScalar(l), + GrIntToScalar(t)); + ((GrPoint*)((intptr_t)this + 1 * stride))->set(GrIntToScalar(l), + GrIntToScalar(b)); + ((GrPoint*)((intptr_t)this + 2 * stride))->set(GrIntToScalar(r), + GrIntToScalar(b)); + ((GrPoint*)((intptr_t)this + 3 * stride))->set(GrIntToScalar(r), + GrIntToScalar(t)); + } + + bool operator ==(const GrPoint& p) const { + return fX == p.fX && fY == p.fY; + } + + bool operator !=(const GrPoint& p) const { + return fX != p.fX || fY != p.fY; + } +}; + +struct GrIPoint16 { + int16_t fX, fY; + + void set(intptr_t x, intptr_t y) { + fX = GrToS16(x); + fY = GrToS16(y); + } +}; + +struct GrVec { +public: + GrScalar fX, fY; + + GrVec() {} + GrVec(GrScalar x, GrScalar y) { fX = x; fY = y; } + + GrScalar x() const { return fX; } + GrScalar y() const { return fY; } + + /** + * set x and y length of the vector. + */ + void set(GrScalar x, GrScalar y) { + fX = x; + fY = y; + } + + /** + * set vector to point from a to b. + */ + void setBetween(const GrPoint& a, const GrPoint& b) { + fX = b.fX - a.fX; + fY = b.fY - a.fY; + } + + /** + * length of the vector squared. + */ + GrScalar lengthSqd() const { + return GrMul(fX, fX) + GrMul(fY, fY); + } + + /** + * length of the vector. + */ + GrScalar length() const { + // TODO: fixed point sqrt + return GrFloatToScalar(sqrtf(GrScalarToFloat(lengthSqd()))); + } + + /** + * normalizes the vector if it's length is not 0. + * @return true if normalized, otherwise false. + */ + bool normalize() { + GrScalar l = lengthSqd(); + if (l) { + // TODO: fixed point sqrt and invert + l = 1 / sqrtf(l); + fX *= l; + fY *= l; + return true; + } + return false; + } + + /** + * Dot product of this with vec. + */ + GrScalar dot(const GrVec& vec) const { + return GrMul(vec.fX, fX) + GrMul(vec.fY, fY); + } + + /** + * z-value of this cross vec. + */ + GrScalar cross(const GrVec& vec) const { + return GrMul(fX, vec.fY) - GrMul(fY, vec.fX); + } + + bool operator ==(const GrPoint& p) const { + return fX == p.fX && fY == p.fY; + } + + bool operator !=(const GrPoint& p) const { + return fX != p.fX || fY != p.fY; + } +}; + +GrScalar GrPoint::distanceToLineBetweenSqd(const GrPoint& a, + const GrPoint& b) const { + // Let d be the distance between c (this) and line ab. + // The area of the triangle defined by a, b, and c is + // A = |b-a|*d/2. Let u = b-a and v = c-a. The cross product of + // u and v is aligned with the z axis and its magnitude is 2A. + // So d = |u x v| / |u|. + GrVec u, v; + u.setBetween(a,b); + v.setBetween(a,*this); + + GrScalar det = u.cross(v); + return (GrMul(det, det)) / u.lengthSqd(); +} + +GrScalar GrPoint::distanceToLineBetween(const GrPoint& a, + const GrPoint& b) const { + GrVec u, v; + u.setBetween(a,b); + v.setBetween(a,*this); + + GrScalar det = u.cross(v); + return (GrScalarAbs(det)) / u.length(); +} + +GrScalar GrPoint::distanceToLineSegmentBetweenSqd(const GrPoint& a, + const GrPoint& b) const { + // See comments to distanceToLineBetweenSqd. If the projection of c onto + // u is between a and b then this returns the same result as that + // function. Otherwise, it returns the distance to the closer of a and + // b. Let the projection of v onto u be v'. There are three cases: + // 1. v' points opposite to u. c is not between a and b and is closer + // to a than b. + // 2. v' points along u and has magnitude less than y. c is between + // a and b and the distance to the segment is the same as distance + // to the line ab. + // 3. v' points along u and has greater magnitude than u. c is not + // not between a and b and is closer to b than a. + // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're + // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise + // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to + // avoid a sqrt to compute |u|. + + GrVec u, v; + u.setBetween(a,b); + v.setBetween(a,*this); + + GrScalar uLengthSqd = u.lengthSqd(); + GrScalar uDotV = u.dot(v); + + if (uDotV <= 0) { + return v.lengthSqd(); + } else if (uDotV > uLengthSqd) { + return b.distanceToSqd(*this); + } else { + GrScalar det = u.cross(v); + return (GrMul(det, det)) / uLengthSqd; + } +} + +GrScalar GrPoint::distanceToLineSegmentBetween(const GrPoint& a, + const GrPoint& b) const { + // TODO: fixed point sqrt + return GrFloatToScalar(sqrtf(GrScalarToFloat(distanceToLineSegmentBetweenSqd(a,b)))); +} + + +#endif + diff --git a/gpu/include/GrRandom.h b/gpu/include/GrRandom.h new file mode 100644 index 0000000000..408f61de7b --- /dev/null +++ b/gpu/include/GrRandom.h @@ -0,0 +1,62 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrRandom_DEFINED +#define GrRandom_DEFINED + +class GrRandom { +public: + GrRandom() : fSeed(0) {} + GrRandom(uint32_t seed) : fSeed(seed) {} + + uint32_t seed() const { return fSeed; } + + uint32_t nextU() { + fSeed = fSeed * kMUL + kADD; + return fSeed; + } + + int32_t nextS() { return (int32_t)this->nextU(); } + + /** + * Returns value [0...1) as a float + */ + float nextF() { + // const is 1 / (2^32 - 1) + return (float)(this->nextU() * 2.32830644e-10); + } + + /** + * Returns value [min...max) as a float + */ + float nextF(float min, float max) { + return min + this->nextF() * (max - min); + } + +private: + /* + * These constants taken from "Numerical Recipes in C", reprinted 1999 + */ + enum { + kMUL = 1664525, + kADD = 1013904223 + }; + uint32_t fSeed; +}; + +#endif + diff --git a/gpu/include/GrRect.h b/gpu/include/GrRect.h new file mode 100644 index 0000000000..5192ebdf18 --- /dev/null +++ b/gpu/include/GrRect.h @@ -0,0 +1,284 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrRect_DEFINED +#define GrRect_DEFINED + +#include "GrPoint.h" + +struct GrIRect { + int32_t fLeft, fTop, fRight, fBottom; + + GrIRect() {} + GrIRect(int32_t left, int32_t top, int32_t right, int32_t bottom) { + fLeft = left; + fTop = top; + fRight = right; + fBottom = bottom; + } + + int32_t x() const { return fLeft; } + int32_t y() const { return fTop; } + int32_t width() const { return fRight - fLeft; } + int32_t height() const { return fBottom - fTop; } + + bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + bool isInverted() const { return fLeft > fRight || fTop > fBottom; } + + void setEmpty() { fLeft = fTop = fRight = fBottom = 0; } + + void setXYWH(int32_t x, int32_t y, int32_t w, int32_t h) { + fLeft = x; + fTop = y; + fRight = x + w; + fBottom = y + h; + } + + void setLTRB(int32_t l, int32_t t, int32_t r, int32_t b) { + fLeft = l; + fTop = t; + fRight = r; + fBottom = b; + } + + /** + * Make the largest representable rectangle + + */ + void setLargest() { + fLeft = fTop = GR_Int32Min; + fRight = fBottom = GR_Int32Max; + } + + bool quickReject(int l, int t, int r, int b) const { + return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b; + } + + void unionWith(const GrIRect& r) { + if (fLeft > r.fLeft) fLeft = r.fLeft; + if (fTop > r.fTop) fTop = r.fTop; + if (fRight < r.fRight) fRight = r.fRight; + if (fBottom < r.fBottom) fBottom = r.fBottom; + } + + friend bool operator==(const GrIRect& a, const GrIRect& b) { + return 0 == memcmp(&a, &b, sizeof(a)); + } + + friend bool operator!=(const GrIRect& a, const GrIRect& b) { + return 0 != memcmp(&a, &b, sizeof(a)); + } + + bool equalsLTRB(int l, int t, int r, int b) const { + return fLeft == l && fTop == t && + fRight == r && fBottom == b; + } + bool equalsXYWH(int x, int y, int w, int h) const { + return fLeft == x && fTop == y && + this->width() == w && this->height() == h; + } + + bool contains(const GrIRect& r) const { + return fLeft <= r.fLeft && + fRight >= r.fRight && + fTop <= r.fTop && + fBottom >= r.fBottom; + } +}; + +struct GrIRect16 { + int16_t fLeft, fTop, fRight, fBottom; + + int width() const { return fRight - fLeft; } + int height() const { return fBottom - fTop; } + int area() const { return this->width() * this->height(); } + bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + + void set(const GrIRect& r) { + fLeft = GrToS16(r.fLeft); + fTop = GrToS16(r.fTop); + fRight = GrToS16(r.fRight); + fBottom = GrToS16(r.fBottom); + } +}; + +/** + * 2D Rect struct + */ +struct GrRect { + GrScalar fLeft, fTop, fRight, fBottom; + + /** + * Uninitialized rectangle. + */ + GrRect() {} + + /** + * Initialize a rectangle to a point. + * @param pt the point used to initialize the rectanglee. + */ + GrRect(GrPoint pt) { + setToPoint(pt); + } + + GrRect(GrScalar left, GrScalar top, GrScalar right, GrScalar bottom) { + fLeft = left; + fTop = top; + fRight = right; + fBottom = bottom; + } + + explicit GrRect(const GrIRect& src) { + fLeft = GrIntToScalar(src.fLeft); + fTop = GrIntToScalar(src.fTop); + fRight = GrIntToScalar(src.fRight); + fBottom = GrIntToScalar(src.fBottom); + } + + GrScalar x() const { return fLeft; } + GrScalar y() const { return fTop; } + GrScalar width() const { return fRight - fLeft; } + GrScalar height() const { return fBottom - fTop; } + + GrScalar left() const { return fLeft; } + GrScalar top() const { return fTop; } + GrScalar right() const { return fRight; } + GrScalar bottom() const { return fBottom; } + + GrScalar diagonalLengthSqd() const { + GrScalar w = width(); + GrScalar h = height(); + return GrMul(w, w) + GrMul(h, h); + } + + GrScalar diagonalLength() const { + // TODO: fixed point sqrt + return GrFloatToScalar(sqrtf(GrScalarToFloat(diagonalLengthSqd()))); + } + + /** + * Returns true if the width or height is <= 0 + */ + bool isEmpty() const { + return fLeft >= fRight || fTop >= fBottom; + } + + void setEmpty() { + fLeft = fTop = fRight = fBottom = 0; + } + + /** + * returns true if the rectangle is inverted either in x or y + */ + bool isInverted() const { + return (fLeft > fRight) || (fTop > fBottom); + } + + /** + * Initialize a rectangle to a point. + * @param pt the point used to initialize the rectangle. + */ + void setToPoint(const GrPoint& pt) { + fLeft = pt.fX; + fTop = pt.fY; + fRight = pt.fX; + fBottom = pt.fY; + } + + void set(const GrIRect& r) { + fLeft = GrIntToScalar(r.fLeft); + fTop = GrIntToScalar(r.fTop); + fRight = GrIntToScalar(r.fRight); + fBottom = GrIntToScalar(r.fBottom); + } + + void roundOut(GrIRect* r) const { + r->setLTRB(GrScalarFloorToInt(fLeft), + GrScalarFloorToInt(fTop), + GrScalarCeilToInt(fRight), + GrScalarCeilToInt(fBottom)); + } + + /** + * Set the rect to the union of the array of points. If the array is empty + * the rect will be empty [0,0,0,0] + */ + void setBounds(const GrPoint pts[], int count); + + /** + * Make the largest representable rectangle + * Set the rect to fLeft = fTop = GR_ScalarMin and + * fRight = fBottom = GR_ScalarMax. + */ + void setLargest() { + fLeft = fTop = GR_ScalarMin; + fRight = fBottom = GR_ScalarMax; + } + + /** + Set the rect to fLeft = fTop = GR_ScalarMax and + fRight = fBottom = GR_ScalarMin. + Useful for initializing a bounding rectangle. + */ + void setLargestInverted() { + fLeft = fTop = GR_ScalarMax; + fRight = fBottom = GR_ScalarMin; + } + + void setLTRB(GrScalar left, + GrScalar top, + GrScalar right, + GrScalar bottom) { + fLeft = left; + fTop = top; + fRight = right; + fBottom = bottom; + } + + void setXYWH(GrScalar x, GrScalar y, GrScalar width, GrScalar height) { + fLeft = x; + fTop = y; + fRight = x + width; + fBottom = y + height; + } + + /** + Expand the edges of the rectangle to include a point. + Useful for constructing a bounding rectangle. + @param pt the point used to grow the rectangle. + */ + void growToInclude(const GrPoint& pt) { + fLeft = GrMin(pt.fX, fLeft); + fRight = GrMax(pt.fX, fRight); + + fTop = GrMin(pt.fY, fTop); + fBottom = GrMax(pt.fY, fBottom); + } + + /** + * Assigns 4 sequential points in order to construct a counter-clockwise + * triangle fan, given the corners of this rect. Returns the address of + * the next point, treating pts as an array. + */ + GrPoint* setRectFan(GrPoint pts[4]) const { + pts->setRectFan(fLeft, fTop, fRight, fBottom); + return pts + 4; + } +}; + +#endif + diff --git a/gpu/include/GrRectanizer.h b/gpu/include/GrRectanizer.h new file mode 100644 index 0000000000..50bb8fed24 --- /dev/null +++ b/gpu/include/GrRectanizer.h @@ -0,0 +1,64 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrRectanizer_DEFINED +#define GrRectanizer_DEFINED + +#include "GrRect.h" +#include "GrTDArray.h" + +class GrRectanizerPurgeListener { +public: + virtual ~GrRectanizerPurgeListener() {} + + virtual void notifyPurgeStrip(void*, int yCoord) = 0; +}; + +class GrRectanizer { +public: + GrRectanizer(int width, int height) : fWidth(width), fHeight(height) { + GrAssert(width >= 0); + GrAssert(height >= 0); + } + + virtual ~GrRectanizer() {} + + int width() const { return fWidth; } + int height() const { return fHeight; } + + virtual bool addRect(int width, int height, GrIPoint16* loc) = 0; + virtual float percentFull() const = 0; + + // return the Y-coordinate of a strip that should be purged, given height + // i.e. return the oldest such strip, or some other criteria. Return -1 + // if there is no candidate + virtual int stripToPurge(int height) const = 0; + virtual void purgeStripAtY(int yCoord) = 0; + + /** + * Our factory, which returns the subclass du jour + */ + static GrRectanizer* Factory(int width, int height); + +private: + int fWidth; + int fHeight; +}; + +#endif + + diff --git a/gpu/include/GrRefCnt.h b/gpu/include/GrRefCnt.h new file mode 100644 index 0000000000..7204aff198 --- /dev/null +++ b/gpu/include/GrRefCnt.h @@ -0,0 +1,125 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrRefCnt_DEFINED +#define GrRefCnt_DEFINED + +#include "GrTypes.h" +#include "GrNoncopyable.h" + +/** + * Base class for reference counting. When an object is first instantiated, + * its reference count is 1. If the object may be null, use GrSafeRef() and + * GrSafeUnref(). + * + * It is an error (though only checked for in the debug build) to call unref() + * such that the reference count becomes 0. + */ +class GrRefCnt : GrNoncopyable { +public: + GrRefCnt() : fRefCnt(1) {} + virtual ~GrRefCnt() { + GrAssert(1 == fRefCnt); +#if GR_DEBUG + fRefCnt = 0; // force validate() to trigger if called afterwards +#endif + } + + int32_t refcnt() const { return fRefCnt; } + + void ref() const { + GrAssert(fRefCnt > 0); + ++fRefCnt; + } + + void unref() const { + GrAssert(fRefCnt > 0); + if (1 == fRefCnt) { + delete this; + } else { + --fRefCnt; + } + } + +#if GR_DEBUG + void validate() const { + GrAssert(fRefCnt > 0); + } +#else + void validate() const {} +#endif + +private: + mutable int32_t fRefCnt; +}; + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Call with instance/subclass of GrRefCnt. This does nothing if obj is null, + * but otherwise it calls ref(). + */ +static inline void GrSafeRef(const GrRefCnt* obj) { + if (obj) { + obj->ref(); + } +} + +/** + * Call with instance/subclass of GrRefCnt. This does nothing if obj is null, + * but otherwise it calls unref(). + */ +static inline void GrSafeUnref(const GrRefCnt* obj) { + if (obj) { + obj->unref(); + } +} + +/** + * Assigns src to dst, checking for NULLs in each, and correctly incrementing + * the reference count of src, and decrementing the reference count of dst + */ +static inline void GrSafeAssign(GrRefCnt*& dst, GrRefCnt* src) { + if (src) { + src->ref(); + } + if (dst) { + dst->unref(); + } + dst = src; +} + +/////////////////////////////////////////////////////////////////////////////// + +class GrAutoRef : GrNoncopyable { +public: + GrAutoRef(GrRefCnt* obj) : fObj(obj) { GrSafeRef(obj); } + ~GrAutoRef() { GrSafeUnref(fObj); } +private: + GrRefCnt* fObj; +}; + +class GrAutoUnref : GrNoncopyable { +public: + GrAutoUnref(GrRefCnt* obj) : fObj(obj) {} + ~GrAutoUnref() { GrSafeUnref(fObj); } +private: + GrRefCnt* fObj; +}; + +#endif + diff --git a/gpu/include/GrSamplerState.h b/gpu/include/GrSamplerState.h new file mode 100644 index 0000000000..06c2346d93 --- /dev/null +++ b/gpu/include/GrSamplerState.h @@ -0,0 +1,130 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrSamplerState_DEFINED +#define GrSamplerState_DEFINED + +#include "GrTypes.h" + +class GrSamplerState { +public: + enum SampleMode { + kNormal_SampleMode, //!< sample color directly + kAlphaMod_SampleMode, //!< modulate with alpha only + kRadial_SampleMode, //!< treat as radial gradient + kRadial2_SampleMode, //!< treat as 2-point radial gradient + kSweep_SampleMode, //!< treat as sweep gradient + }; + + /** + * Describes how a texture is sampled when coordinates are outside the + * texture border + */ + enum WrapMode { + kClamp_WrapMode, + kRepeat_WrapMode, + kMirror_WrapMode + }; + + /** + * Default sampler state is set to kClamp and no-filter + */ + GrSamplerState() { + this->setClampNoFilter(); + } + + GrSamplerState(bool filter) { + fWrapX = kClamp_WrapMode; + fWrapY = kClamp_WrapMode; + fSampleMode = kNormal_SampleMode; + fFilter = filter; + } + + GrSamplerState(WrapMode wx, WrapMode wy, bool filter) { + fWrapX = wx; + fWrapY = wy; + fSampleMode = kNormal_SampleMode; + fFilter = filter; + } + + GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample, bool filter) { + fWrapX = wx; + fWrapY = wy; + fSampleMode = sample; + fFilter = filter; + } + + WrapMode getWrapX() const { return fWrapX; } + WrapMode getWrapY() const { return fWrapY; } + SampleMode getSampleMode() const { return fSampleMode; } + bool isFilter() const { return fFilter; } + + bool isGradient() const { + return kRadial_SampleMode == fSampleMode || + kRadial2_SampleMode == fSampleMode || + kSweep_SampleMode == fSampleMode; + } + + void setWrapX(WrapMode mode) { fWrapX = mode; } + void setWrapY(WrapMode mode) { fWrapY = mode; } + void setSampleMode(SampleMode mode) { fSampleMode = mode; } + void setFilter(bool filter) { fFilter = filter; } + + void setClampNoFilter() { + fWrapX = kClamp_WrapMode; + fWrapY = kClamp_WrapMode; + fSampleMode = kNormal_SampleMode; + fFilter = false; + } + + GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; } + GrScalar getRadial2Radius0() const { return fRadial2Radius0; } + bool isRadial2PosRoot() const { return fRadial2PosRoot; } + + /** + * Sets the parameters for kRadial2_SampleMode. The texture + * matrix must be set so that the first point is at (0,0) and the second + * point lies on the x-axis. The second radius minus the first is 1 unit. + * The additional parameters to define the gradient are specified by this + * function. + */ + void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) { + fRadial2CenterX1 = centerX1; + fRadial2Radius0 = radius0; + fRadial2PosRoot = posRoot; + } + + static const GrSamplerState& ClampNoFilter() { + return gClampNoFilter; + } + +private: + WrapMode fWrapX; + WrapMode fWrapY; + SampleMode fSampleMode; + bool fFilter; + + // these are undefined unless fSampleMode == kRadial2_SampleMode + GrScalar fRadial2CenterX1; + GrScalar fRadial2Radius0; + bool fRadial2PosRoot; + + static const GrSamplerState gClampNoFilter; +}; + +#endif + diff --git a/gpu/include/GrScalar.h b/gpu/include/GrScalar.h new file mode 100644 index 0000000000..1353fb2148 --- /dev/null +++ b/gpu/include/GrScalar.h @@ -0,0 +1,116 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrScalar_DEFINED +#define GrScalar_DEFINED + +#include "GrTypes.h" + +#include <float.h> +#include <math.h> + +#define GR_Int32Max (0x7fffffff) +#define GR_Int32Min (0x80000000) + +/** + * Convert an int to fixed point + */ +#if GR_DEBUG + inline GrFixed GrIntToFixed(int i) { + GrAssert(((i & 0xffff0000) == 0xffff0000) || ((i & 0xffff0000) == 0x0)); + return i << 16; + } +#else + #define GrIntToFixed(i) (GrFixed)((i) << 16) +#endif + +#define GR_Fixed1 (1 << 16) +#define GR_FixedHalf (1 << 15) +#define GR_FixedMax GR_Int32Max +#define GR_FixedMin GR_Int32Min + +#define GrFixedFloorToFixed(x) ((x) & ~0xFFFF) +#define GrFixedFloorToInt(x) ((x) >> 16) + +/** + * Convert fixed point to floating point + */ +#define GrFixedToFloat(x) ((x) * 0.0000152587890625f) + +/** + * Convert floating point to fixed point + */ +#define GrFloatToFixed(x) ((GrFixed)((x) * GR_Fixed1)) + +inline GrFixed GrFixedAbs(GrFixed x) { + int32_t s = (x & 0x80000000) >> 31; + return (GrFixed)(((int32_t)x ^ s) - s); +} + +/////////////////////////////////////////////////////////////////////////////// + +#if GR_SCALAR_IS_FIXED + typedef GrFixed GrScalar; + #define GrIntToScalar(x) GrIntToFixed(x) + #define GrFixedToScalar(x) (x) + #define GrScalarToFloat(x) GrFixedToFloat(x) + #define GrFloatToScalar(x) GrFloatToFixed(x) + #define GrScalarHalf(x) ((x) >> 1) + #define GrScalarAve(x,y) (((x)+(y)) >> 1) + #define GrScalarAbs(x) GrFixedAbs(x) + #define GR_Scalar1 GR_Fixed1 + #define GR_ScalarHalf GR_FixedHalf + #define GR_ScalarMax GR_FixedMax + #define GR_ScalarMin GR_FixedMin +#elif GR_SCALAR_IS_FLOAT + typedef float GrScalar; + #define GrIntToScalar(x) ((GrScalar)x) + #define GrFixedToScalar(x) GrFixedToFloat(x) + #define GrScalarToFloat(x) (x) + #define GrFloatToScalar(x) (x) + #define GrScalarHalf(x) ((x) * 0.5f) + #define GrScalarAbs(x) fabsf(x) + #define GrScalarAve(x,y) (((x) + (y)) * 0.5f) + #define GR_Scalar1 1.f + #define GR_ScalarHalf 0.5f + #define GR_ScalarMax (FLT_MAX) + #define GR_ScalarMin (-FLT_MAX) + + static inline int32_t GrScalarFloorToInt(float x) { + return (int32_t)::floorf(x); + } + static inline int32_t GrScalarCeilToInt(float x) { + return (int32_t)::ceilf(x); + } +#else + #error "Scalar type not defined" +#endif + +/** + * Multiply two GrScalar values + */ +static inline GrScalar GrMul(GrScalar a, GrScalar b) { +#if GR_SCALAR_IS_FLOAT + return a * b; +#else + int64_t tmp = (int64_t)a * b; + return (tmp + GR_FixedHalf) >> 16; +#endif +} + +#endif + diff --git a/gpu/include/GrStopwatch.h b/gpu/include/GrStopwatch.h new file mode 100644 index 0000000000..4945897431 --- /dev/null +++ b/gpu/include/GrStopwatch.h @@ -0,0 +1,135 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrStopwatch_DEFINED +#define GrStopwatch_DEFINED + +#include "GrTypes.h" + +template <typename PLATFORM_TIMER> +/** + * Base class for stopwatch. Relies on PLATFORM_TIMER for platform-specific + * timer functions. PLATFORM_TIMER provides: + * - typename TIMESTAMP : a timestamp value that can be used with Diff() + * - static TIMESTAMP Now() : gets current timestamp + * - static double Diff(const TIMESTAMP& begin, const TIMESTAMP& end) : + * computes delta in seconds between two timestamps + */ +class GrStopwatchBase { +public: + /** + * Contructor - implicit reset() + */ + GrStopwatchBase() { + fRunning = false; + fTotalElapsed = 0.0; + } + + /** + * begins a new lap + */ + void start() { + double lastLap = lapTime(); + fTotalElapsed += lastLap; + fRunning = true; + fLastStart = PLATFORM_TIMER::Now(); + } + + /** + * ends current lap (or no effect if lap not started) + */ + void stop() { + double lastLap = lapTime(); + fTotalElapsed += lastLap; + fRunning = false; + } + + /** + * ends current lap, resets total time + */ + void reset() { + fRunning = false; + fTotalElapsed = 0.f; + } + + /** + * Computes the time of all laps since last reset() including current lap + * if lap is still running. + * + * @return the sum time in seconds of all laps since last reset(). + */ + double totalTime() const { + return fTotalElapsed + lapTime(); + } + + /** + * Current lap time. + * + * @return time in seconds of current lap if one is running otherwise 0. + */ + double lapTime() const { + if (fRunning) { + PLATFORM_TIMER::Timestamp now = PLATFORM_TIMER::Now(); + return PLATFORM_TIMER::Elapsed(fLastStart, now); + } + return 0.0; + } + +private: + double fTotalElapsed; + + typename PLATFORM_TIMER::Timestamp fLastStart; + bool fRunning; +}; + +#if GR_WIN32_BUILD + + #include <Windows.h> + + class GrWin32Timer { + public: + typedef LARGE_INTEGER Timestamp; + + static Timestamp Now() { + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + return now; + } + + static double Elapsed(const Timestamp& begin, const Timestamp& end) { + double diff = (double)(end.QuadPart - begin.QuadPart); + return diff * Scale(); + } + private: + static double Scale() { + static double scale; + if (0.0 == scale) { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + GrAssert(0 != freq.QuadPart); + scale = 1 / (double) freq.QuadPart; + } + return scale; + } + }; + typedef GrStopwatchBase<GrWin32Timer> GrStopwatch; +#else + #error "Implement platform timer for stopwatch" +#endif + + +#endif diff --git a/gpu/include/GrStringBuilder.h b/gpu/include/GrStringBuilder.h new file mode 100644 index 0000000000..bcf124f337 --- /dev/null +++ b/gpu/include/GrStringBuilder.h @@ -0,0 +1,182 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrStringBuilder_DEFINED +#define GrStringBuilder_DEFINED + +#include <GrTArray.h> +#include <stdio.h> + +// Class used to concat strings together into a single string +// See below for GrSStringBuilder subclass that has a pool of +// stack storage (to avoid malloc). +class GrStringBuilder { +public: + GrStringBuilder() : + fChars() { + fChars.push_back() = '\0'; + } + + GrStringBuilder(const GrStringBuilder& s) : + fChars(s.fChars) { + GrAssert('\0' == s.fChars.back()); + } + + GrStringBuilder(const char* s) : + fChars(s, strlen(s)+1) { + } + + GrStringBuilder(const GrStringBuilder& a, const GrStringBuilder& b) { + GrAssert('\0' == a.fChars.back()); + GrAssert('\0' == b.fChars.back()); + + fChars.push_back_n(a.fChars.count() + b.fChars.count() - 1); + char* s = &fChars.front(); + memcpy(s, &a.fChars.front(), a.fChars.count() - 1); + s += a.fChars.count() - 1; + memcpy(s, &b.fChars.front(), b.fChars.count()); + } + + GrStringBuilder& operator =(const GrStringBuilder& s) { + fChars = s.fChars; + return *this; + } + + GrStringBuilder& operator =(const char* s) { + GrAssert('\0' == fChars.back()); + + int l = strlen(s); + fChars.resize_back(l + 1); + memcpy(&fChars.front(), s, l + 1); + return *this; + } + + GrStringBuilder& operator +=(const GrStringBuilder& s) { + GrAssert('\0' == fChars.back()); + GrAssert('\0' == s.fChars.back()); + fChars.push_back_n(s.length()); + memcpy(&fChars.fromBack(s.length()), &s.fChars.front(), s.fChars.count()); + return *this; + } + + GrStringBuilder& operator +=(const char* s) { + GrAssert('\0' == fChars.back()); + int l = strlen(s); + fChars.push_back_n(l); + memcpy(&fChars.fromBack(l), s, l + 1); + return *this; + } + + GrStringBuilder& operator +=(char c) { + GrAssert('\0' == fChars.back()); + fChars.back() = c; + fChars.push_back() = '\0'; + return *this; + } + + void appendInt(int x) { + GR_STATIC_ASSERT(4 == sizeof(int)); + // -, 10 digits, null char + char temp[12]; + sprintf(temp, "%d", x); + *this += temp; + } + + char& operator [](int i) { + GrAssert(i < length()); + return fChars[i]; + } + + char operator [](int i) const { + GrAssert(i < length()); + return fChars[i]; + } + + const char* cstr() const { return &fChars.front(); } + + int length() const { return fChars.count() - 1; } + +protected: + // helpers for GrSStringBuilder (with storage on the stack) + + GrStringBuilder(void* stackChars, int stackCount) : + fChars(stackCount ? stackChars : NULL, + stackCount) { + fChars.push_back() = '\0'; + } + + GrStringBuilder(void* stackChars, + int stackCount, + const GrStringBuilder& s) : + fChars(s.fChars, + (stackCount ? stackChars : NULL), + stackCount) { + } + + GrStringBuilder(void* stackChars, + int stackCount, + const char* s) : + fChars(s, + strlen(s)+1, + stackCount ? stackChars : NULL, + stackCount) { + } + + GrStringBuilder(void* stackChars, + int stackCount, + const GrStringBuilder& a, + const GrStringBuilder& b) : + fChars(stackCount ? stackChars : NULL, + stackCount) { + GrAssert('\0' == a.fChars.back()); + GrAssert('\0' == b.fChars.back()); + + fChars.push_back_n(a.fChars.count() + b.fChars.count() - 1); + char* s = &fChars.front(); + memcpy(s, &a.fChars.front(), a.fChars.count() - 1); + s += a.fChars.count() - 1; + memcpy(s, &b.fChars.front(), b.fChars.count()); + } + +private: + GrTArray<char, true> fChars; +}; + +template <int STACK_COUNT = 128> +class GrSStringBuilder : public GrStringBuilder { +public: + GrSStringBuilder() : GrStringBuilder(fStackChars, STACK_COUNT) {} + + GrSStringBuilder(const GrStringBuilder& s) : GrStringBuilder(fStackChars, + STACK_COUNT, + s) { + } + + GrSStringBuilder(const char* s) : GrStringBuilder(fStackChars, + STACK_COUNT, + s) { + } + + GrSStringBuilder(const GrStringBuilder& a, const GrStringBuilder& b) : + GrStringBuilder(fStackChars, STACK_COUNT, a, b) { + } +private: + char fStackChars[STACK_COUNT]; +}; + +#endif + diff --git a/gpu/include/GrTArray.h b/gpu/include/GrTArray.h new file mode 100644 index 0000000000..f0d94943a9 --- /dev/null +++ b/gpu/include/GrTArray.h @@ -0,0 +1,298 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTArray_DEFINED +#define GrTArray_DEFINED + +#include <new> +#include "GrTypes.h" + +// TODO: convert from uint32_t to int. + +// DATA_TYPE indicates that T has a trivial cons, destructor +// and can be shallow-copied +template <typename T, bool DATA_TYPE = false> class GrTArray { +public: + GrTArray() { + fCount = 0; + fReserveCount = MIN_ALLOC_COUNT; + fAllocCount = 0; + fMemArray = NULL; + fPreAllocMemArray = NULL; + } + + GrTArray(uint32_t reserveCount) { + fCount = 0; + fReserveCount = GrMax(reserveCount, (uint32_t)MIN_ALLOC_COUNT); + fAllocCount = fReserveCount; + fMemArray = GrMalloc(sizeof(T) * fReserveCount); + fPreAllocMemArray = NULL; + } + + GrTArray(void* preAllocStorage, uint32_t preAllocCount) { + // we allow NULL,0 args and revert to the default cons. behavior + // this makes it possible for a owner-object to use same constructor + // to get either prealloc or nonprealloc behavior based using same line + GrAssert((NULL == preAllocStorage) == !preAllocCount); + + fCount = 0; + fReserveCount = preAllocCount > 0 ? preAllocCount : + MIN_ALLOC_COUNT; + fAllocCount = preAllocCount; + fMemArray = preAllocStorage; + fPreAllocMemArray = preAllocStorage; + } + + GrTArray(const GrTArray& array) { + fCount = array.count(); + fReserveCount = MIN_ALLOC_COUNT; + fAllocCount = GrMax(fReserveCount, fCount); + fMemArray = GrMalloc(sizeof(T) * fAllocCount); + fPreAllocMemArray = NULL; + if (DATA_TYPE) { + memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount); + } else { + for (uint32_t i = 0; i < fCount; ++i) { + new (fItemArray + i) T(array[i]); + } + } + } + + GrTArray(const T* array, uint32_t count) { + fCount = count; + fReserveCount = MIN_ALLOC_COUNT; + fAllocCount = GrMax(fReserveCount, fCount); + fMemArray = GrMalloc(sizeof(T) * fAllocCount); + fPreAllocMemArray = NULL; + if (DATA_TYPE) { + memcpy(fMemArray, array, sizeof(T) * fCount); + } else { + for (uint32_t i = 0; i < fCount; ++i) { + new (fItemArray + i) T(array[i]); + } + } + } + + GrTArray(const GrTArray& array, + void* preAllocStorage, uint32_t preAllocCount) { + + // for same reason as non-copying cons we allow NULL, 0 for prealloc + GrAssert((NULL == preAllocStorage) == !preAllocCount); + + fCount = array.count(); + fReserveCount = preAllocCount > 0 ? preAllocCount : + MIN_ALLOC_COUNT; + fPreAllocMemArray = preAllocStorage; + + if (fReserveCount >= fCount && preAllocCount) { + fAllocCount = fReserveCount; + fMemArray = preAllocStorage; + } else { + fAllocCount = GrMax(fCount, fReserveCount); + fMemArray = GrMalloc(fAllocCount * sizeof(T)); + } + + if (DATA_TYPE) { + memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount); + } else { + for (uint32_t i = 0; i < fCount; ++i) { + new (fItemArray + i) T(array[i]); + } + } + } + + GrTArray(const T* array, uint32_t count, + void* preAllocStorage, uint32_t preAllocCount) { + + // for same reason as non-copying cons we allow NULL, 0 for prealloc + GrAssert((NULL == preAllocStorage) == !preAllocCount); + + fCount = count; + fReserveCount = (preAllocCount > 0) ? preAllocCount : + MIN_ALLOC_COUNT; + fPreAllocMemArray = preAllocStorage; + + if (fReserveCount >= fCount && preAllocCount) { + fAllocCount = fReserveCount; + fMemArray = preAllocStorage; + } else { + fAllocCount = GrMax(fCount, fReserveCount); + fMemArray = GrMalloc(fAllocCount * sizeof(T)); + } + + if (DATA_TYPE) { + memcpy(fMemArray, array, sizeof(T) * fCount); + } else { + for (uint32_t i = 0; i < fCount; ++i) { + new (fItemArray + i) T(array[i]); + } + } + } + + GrTArray& operator =(const GrTArray& array) { + for (uint32_t i = 0; i < fCount; ++i) { + fItemArray[i].~T(); + } + fCount = 0; + checkRealloc((int)array.count()); + fCount = array.count(); + if (DATA_TYPE) { + memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount); + } else { + for (uint32_t i = 0; i < fCount; ++i) { + new (fItemArray + i) T(array[i]); + } + } + return *this; + } + + ~GrTArray() { + for (uint32_t i = 0; i < fCount; ++i) { + fItemArray[i].~T(); + } + if (fMemArray != fPreAllocMemArray) { + GrFree(fMemArray); + } + } + + uint32_t count() const { return fCount; } + + bool empty() const { return !fCount; } + + T& push_back() { + checkRealloc(1); + new ((char*)fMemArray+sizeof(T)*fCount) T; + ++fCount; + return fItemArray[fCount-1]; + } + + void push_back_n(uint32_t n) { + checkRealloc(n); + for (uint32_t i = 0; i < n; ++i) { + new (fItemArray + fCount + i) T; + } + fCount += n; + } + + void pop_back() { + GrAssert(0 != fCount); + --fCount; + fItemArray[fCount].~T(); + checkRealloc(0); + } + + void pop_back_n(uint32_t n) { + GrAssert(fCount >= n); + fCount -= n; + for (uint32_t i = 0; i < n; ++i) { + fItemArray[i].~T(); + } + checkRealloc(0); + } + + // pushes or pops from the back to resize + void resize_back(uint32_t newCount) { + if (newCount > fCount) { + push_back_n(newCount - fCount); + } else if (newCount < fCount) { + pop_back_n(fCount - newCount); + } + } + + T& operator[] (uint32_t i) { + GrAssert(i < fCount); + return fItemArray[i]; + } + + const T& operator[] (uint32_t i) const { + GrAssert(i < fCount); + return fItemArray[i]; + } + + T& front() { GrAssert(fCount); return fItemArray[0];} + + const T& front() const { GrAssert(fCount); return fItemArray[0];} + + T& back() { GrAssert(fCount); return fItemArray[fCount - 1];} + + const T& back() const { GrAssert(fCount); return fItemArray[fCount - 1];} + + T& fromBack(uint32_t i) { + GrAssert(i < fCount); + return fItemArray[fCount - i - 1]; + } + + const T& fromBack(uint32_t i) const { + GrAssert(i < fCount); + return fItemArray[fCount - i - 1]; + } + +private: + static const uint32_t MIN_ALLOC_COUNT = 8; + + inline void checkRealloc(int32_t delta) { + GrAssert(-delta <= (int32_t)fCount); + + uint32_t newCount = fCount + delta; + uint32_t fNewAllocCount = fAllocCount; + + if (newCount > fAllocCount) { + fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1), + fReserveCount); + } else if (newCount < fAllocCount / 3) { + fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount); + } + + if (fNewAllocCount != fAllocCount) { + + fAllocCount = fNewAllocCount; + char* fNewMemArray; + + if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) { + fNewMemArray = (char*) fPreAllocMemArray; + } else { + fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T)); + } + + if (DATA_TYPE) { + memcpy(fNewMemArray, fMemArray, fCount * sizeof(T)); + } else { + for (uint32_t i = 0; i < fCount; ++i) { + new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]); + fItemArray[i].~T(); + } + } + + if (fMemArray != fPreAllocMemArray) { + GrFree(fMemArray); + } + fMemArray = fNewMemArray; + } + } + + uint32_t fReserveCount; + uint32_t fCount; + uint32_t fAllocCount; + void* fPreAllocMemArray; + union { + T* fItemArray; + void* fMemArray; + }; +}; + +#endif + diff --git a/gpu/include/GrTBSearch.h b/gpu/include/GrTBSearch.h new file mode 100644 index 0000000000..264ccb0dbb --- /dev/null +++ b/gpu/include/GrTBSearch.h @@ -0,0 +1,53 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTBSearch_DEFINED +#define GrTBSearch_DEFINED + +template <typename ELEM, typename KEY> +int GrTBSearch(const ELEM array[], int count, KEY target) { + GrAssert(count >= 0); + if (0 == count) { + // we should insert it at 0 + return ~0; + } + + int high = count - 1; + int low = 0; + while (high > low) { + int index = (low + high) >> 1; + if (LT(array[index], target)) { + low = index + 1; + } else { + high = index; + } + } + + // check if we found it + if (EQ(array[high], target)) { + return high; + } + + // now return the ~ of where we should insert it + if (LT(array[high], target)) { + high += 1; + } + return ~high; +} + +#endif + diff --git a/gpu/include/GrTDArray.h b/gpu/include/GrTDArray.h new file mode 100644 index 0000000000..092242e5fc --- /dev/null +++ b/gpu/include/GrTDArray.h @@ -0,0 +1,222 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTDArray_DEFINED +#define GrTDArray_DEFINED + +#include "GrTypes.h" + +static int GrInitialArrayAllocationCount() { + return 4; +} + +static int GrNextArrayAllocationCount(int count) { + return count + ((count + 1) >> 1); +} + +template <typename T> class GrTDArray { +public: + GrTDArray() : fArray(NULL), fAllocated(0), fCount(0) {} + GrTDArray(const GrTDArray& src) { + fCount = fAllocated = src.fCount; + fArray = (T*)GrMalloc(fAllocated * sizeof(T)); + memcpy(fArray, src.fArray, fCount * sizeof(T)); + } + ~GrTDArray() { + if (fArray) { + GrFree(fArray); + } + } + + bool isEmpty() const { return 0 == fCount; } + int count() const { return fCount; } + + const T& at(int index) const { + GrAssert((unsigned)index < (unsigned)fCount); + return fArray[index]; + } + T& at(int index) { + GrAssert((unsigned)index < (unsigned)fCount); + return fArray[index]; + } + + const T& operator[](int index) const { return this->at(index); } + T& operator[](int index) { return this->at(index); } + + GrTDArray& operator=(const GrTDArray& src) { + if (fAllocated < src.fCount) { + fAllocated = src.fCount; + GrFree(fArray); + fArray = (T*)GrMalloc(fAllocated * sizeof(T)); + } + fCount = src.fCount; + memcpy(fArray, src.fArray, fCount * sizeof(T)); + return *this; + } + + void reset() { + if (fArray) { + GrFree(fArray); + fArray = NULL; + } + fAllocated = fCount = 0; + } + + T* begin() const { return fArray; } + T* end() const { return fArray + fCount; } + T* back() const { GrAssert(fCount); return fArray + (fCount - 1); } + + T* prepend() { + this->growAt(0); + return fArray; + } + + T* append() { + this->growAt(fCount); + return fArray + fCount - 1; + } + + /** + * index may be [0..count], so that you can insert at the end (like append) + */ + T* insert(int index) { + GrAssert((unsigned)index <= (unsigned)fCount); + this->growAt(index); + return fArray + index; + } + + void remove(int index) { + GrAssert((unsigned)index < (unsigned)fCount); + fCount -= 1; + if (index < fCount) { + int remaining = fCount - index; + memmove(fArray + index, fArray + index + 1, remaining * sizeof(T)); + } + } + + void removeShuffle(int index) { + GrAssert((unsigned)index < (unsigned)fCount); + fCount -= 1; + if (index < fCount) { + memmove(fArray + index, fArray + fCount, sizeof(T)); + } + } + + // Utility iterators + + /** + * Calls GrFree() on each element. Assumes each is NULL or was allocated + * with GrMalloc(). + */ + void freeAll() { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + GrFree(*curr); + } + this->reset(); + } + + /** + * Calls delete on each element. Assumes each is NULL or was allocated + * with new. + */ + void deleteAll() { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + delete *curr; + } + this->reset(); + } + + /** + * Calls GrSafeUnref() on each element. Assumes each is NULL or is a + * subclass of GrRefCnt. + */ + void unrefAll() { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + GrSafeUnref(*curr); + } + this->reset(); + } + + void visit(void visitor(T&)) const { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + if (*curr) { + visitor(*curr); + } + } + } + + int find(const T& elem) const { + int count = this->count(); + T* curr = this->begin(); + for (int i = 0; i < count; i++) { + if (elem == curr[i]) { + return i; + } + } + return -1; + } + + friend bool operator==(const GrTDArray<T>& a, const GrTDArray<T>& b) { + return a.count() == b.count() && + (0 == a.count() || + 0 == memcmp(a.begin(), b.begin(), a.count() * sizeof(T))); + } + friend bool operator!=(const GrTDArray<T>& a, const GrTDArray<T>& b) { + return !(a == b); + } + +private: + T* fArray; + int fAllocated, fCount; + + // growAt will increment fCount, reallocate fArray (as needed), and slide + // the contents of fArray to make a hole for new data at index. + void growAt(int index) { + GrAssert(fCount <= fAllocated); + if (0 == fAllocated) { + fAllocated = GrInitialArrayAllocationCount(); + fArray = (T*)GrMalloc(fAllocated * sizeof(T)); + } else if (fCount == fAllocated) { + fAllocated = GrNextArrayAllocationCount(fAllocated); + T* newArray = (T*)GrMalloc(fAllocated * sizeof(T)); + memcpy(newArray, fArray, index * sizeof(T)); + memcpy(newArray + index + 1, fArray + index, + (fCount - index) * sizeof(T)); + GrFree(fArray); + fArray = newArray; + } else { + // check that we're not just appending + if (index < fCount) { + memmove(fArray + index + 1, fArray + index, + (fCount - index) * sizeof(T)); + } + } + GrAssert(fCount < fAllocated); + fCount += 1; + } +}; + +extern void* GrTDArray_growAt(void*, int* allocated, int& count, int index, + size_t); + + +#endif + diff --git a/gpu/include/GrTHashCache.h b/gpu/include/GrTHashCache.h new file mode 100644 index 0000000000..510f9ab205 --- /dev/null +++ b/gpu/include/GrTHashCache.h @@ -0,0 +1,226 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTHashCache_DEFINED +#define GrTHashCache_DEFINED + +#include "GrTDArray.h" + +/** + * Key needs + * static bool EQ(const Entry&, const HashKey&); + * static bool LT(const Entry&, const HashKey&); + * uint32_t getHash() const; + * + * Allows duplicate key entries but on find you may get + * any of the duplicate entries returned. + */ +template <typename T, typename Key, size_t kHashBits> class GrTHashTable { +public: + GrTHashTable() { Gr_bzero(fHash, sizeof(fHash)); } + ~GrTHashTable() {} + + int count() const { return fSorted.count(); } + T* find(const Key&) const; + // return true if key was unique when inserted. + bool insert(const Key&, T*); + void remove(const Key&, const T*); + T* removeAt(int index, uint32_t hash); + void removeAll(); + void deleteAll(); + void unrefAll(); + + /** + * Return the index for the element, using a linear search. + */ + int slowFindIndex(T* elem) const { return fSorted.find(elem); } + +#if GR_DEBUG + void validate() const; + bool contains(T*) const; +#endif + + // testing + const GrTDArray<T*>& getArray() const { return fSorted; } +private: + enum { + kHashCount = 1 << kHashBits, + kHashMask = kHashCount - 1 + }; + static unsigned hash2Index(uint32_t hash) { + hash ^= hash >> 16; + if (kHashBits <= 8) { + hash ^= hash >> 8; + } + return hash & kHashMask; + } + + mutable T* fHash[kHashCount]; + GrTDArray<T*> fSorted; + + // search fSorted, and return the found index, or ~index of where it + // should be inserted + int searchArray(const Key&) const; +}; + +/////////////////////////////////////////////////////////////////////////////// + +template <typename T, typename Key, size_t kHashBits> +int GrTHashTable<T, Key, kHashBits>::searchArray(const Key& key) const { + int count = fSorted.count(); + if (0 == count) { + // we should insert it at 0 + return ~0; + } + + const T* const* array = fSorted.begin(); + int high = count - 1; + int low = 0; + while (high > low) { + int index = (low + high) >> 1; + if (Key::LT(*array[index], key)) { + low = index + 1; + } else { + high = index; + } + } + + // check if we found it + if (Key::EQ(*array[high], key)) { + // above search should have found the first occurrence if there + // are multiple. + GrAssert(0 == high || Key::LT(*array[high - 1], key)); + return high; + } + + // now return the ~ of where we should insert it + if (Key::LT(*array[high], key)) { + high += 1; + } + return ~high; +} + +template <typename T, typename Key, size_t kHashBits> +T* GrTHashTable<T, Key, kHashBits>::find(const Key& key) const { + int hashIndex = hash2Index(key.getHash()); + T* elem = fHash[hashIndex]; + + if (NULL == elem || !Key::EQ(*elem, key)) { + // bsearch for the key in our sorted array + int index = this->searchArray(key); + if (index < 0) { + return NULL; + } + elem = fSorted[index]; + // update the hash + fHash[hashIndex] = elem; + } + return elem; +} + +template <typename T, typename Key, size_t kHashBits> +bool GrTHashTable<T, Key, kHashBits>::insert(const Key& key, T* elem) { + int index = this->searchArray(key); + bool first = index < 0; + if (first) { + // turn it into the actual index + index = ~index; + } + // add it to our array + *fSorted.insert(index) = elem; + // update our hash table (overwrites any dupe's position in the hash) + fHash[hash2Index(key.getHash())] = elem; + return first; +} + +template <typename T, typename Key, size_t kHashBits> +void GrTHashTable<T, Key, kHashBits>::remove(const Key& key, const T* elem) { + int index = hash2Index(key.getHash()); + if (fHash[index] == elem) { + fHash[index] = NULL; + } + + // remove from our sorted array + index = this->searchArray(key); + GrAssert(index >= 0); + // if there are multiple matches searchArray will give us the first match + // march forward until we find elem. + while (elem != fSorted[index]) { + ++index; + GrAssert(index < fSorted.count()); + } + GrAssert(elem == fSorted[index]); + fSorted.remove(index); +} + +template <typename T, typename Key, size_t kHashBits> +T* GrTHashTable<T, Key, kHashBits>::removeAt(int elemIndex, uint32_t hash) { + int hashIndex = hash2Index(hash); + if (fHash[hashIndex] == fSorted[elemIndex]) { + fHash[hashIndex] = NULL; + } + // remove from our sorted array + T* elem = fSorted[elemIndex]; + fSorted.remove(elemIndex); + return elem; +} + +template <typename T, typename Key, size_t kHashBits> +void GrTHashTable<T, Key, kHashBits>::removeAll() { + fSorted.reset(); + Gr_bzero(fHash, sizeof(fHash)); +} + +template <typename T, typename Key, size_t kHashBits> +void GrTHashTable<T, Key, kHashBits>::deleteAll() { + fSorted.deleteAll(); + Gr_bzero(fHash, sizeof(fHash)); +} + +template <typename T, typename Key, size_t kHashBits> +void GrTHashTable<T, Key, kHashBits>::unrefAll() { + fSorted.unrefAll(); + Gr_bzero(fHash, sizeof(fHash)); +} + +#if GR_DEBUG +template <typename T, typename Key, size_t kHashBits> +void GrTHashTable<T, Key, kHashBits>::validate() const { + for (size_t i = 0; i < GR_ARRAY_COUNT(fHash); i++) { + if (fHash[i]) { + unsigned hashIndex = hash2Index(Key::GetHash(*fHash[i])); + GrAssert(hashIndex == i); + } + } + + int count = fSorted.count(); + for (int i = 1; i < count; i++) { + GrAssert(Key::LT(*fSorted[i - 1], *fSorted[i]) || + Key::EQ(*fSorted[i - 1], *fSorted[i])); + } +} + +template <typename T, typename Key, size_t kHashBits> +bool GrTHashTable<T, Key, kHashBits>::contains(T* elem) const { + int index = fSorted.find(elem); + return index >= 0; +} + +#endif + +#endif + diff --git a/gpu/include/GrTLList.h b/gpu/include/GrTLList.h new file mode 100644 index 0000000000..1f59635ad4 --- /dev/null +++ b/gpu/include/GrTLList.h @@ -0,0 +1,61 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTLList_DEFINED +#define GrTLList_DEFINED + +#include "GrNoncopyable.h" + +template <typename T> class GrTLList : GrNoncopyable { +public: + class Entry { + Entry* fPrev; + Entry* fNext; + }; + + GrTLList() : fHead(NULL), fTail(NULL) {} +#if GR_DEBUG + ~GrTLList() { + GrAssert(NULL == fHead); + GrAssert(NULL == ftail); + } +#endif + + T* head() const { return fHead; } + T* tail() const { return fTail; } + + void addToHead(T*); + void addToTail(T*); + void removeFromList(T*); + +private: + Entry* fHead; + Entry* fTail; + + friend class Entry; +}; + + +class Parent { + GrTDLList<Child> fList; +}; + +class Child : public GrTLList::Entry<Child> { +}; + +#endif + diff --git a/gpu/include/GrTextContext.h b/gpu/include/GrTextContext.h new file mode 100644 index 0000000000..6b7446b4be --- /dev/null +++ b/gpu/include/GrTextContext.h @@ -0,0 +1,67 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTextContext_DEFINED +#define GrTextContext_DEFINED + +#include "GrGlyph.h" +#include "GrGpuVertex.h" + +class GrContext; +class GrTextStrike; +class GrFontScaler; + +class GrTextContext { +public: + GrTextContext(GrContext*, const GrMatrix* extMatrix = NULL); + ~GrTextContext(); + + void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, + GrFontScaler*); + + void flush(); // optional; automatically called by destructor + +private: + GrContext* fContext; + GrDrawTarget* fDrawTarget; + + GrMatrix fExtMatrix; + GrFontScaler* fScaler; + GrTextStrike* fStrike; + + inline void flushGlyphs(); + + enum { + kMinRequestedGlyphs = 1, + kDefaultRequestedGlyphs = 64, + kMinRequestedVerts = kMinRequestedGlyphs * 4, + kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, + }; + + GrGpuTextVertex* fVertices; + + int32_t fMaxVertices; + GrTexture* fCurrTexture; + int fCurrVertex; + + GrIRect fClipRect; + GrMatrix fOrigViewMatrix; // restore previous viewmatrix +}; + +#endif + + diff --git a/gpu/include/GrTextStrike.h b/gpu/include/GrTextStrike.h new file mode 100644 index 0000000000..abafa57130 --- /dev/null +++ b/gpu/include/GrTextStrike.h @@ -0,0 +1,119 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTextStrike_DEFINED +#define GrTextStrike_DEFINED + +#include "GrAllocPool.h" +#include "GrFontScaler.h" +#include "GrTHashCache.h" +#include "GrPoint.h" +#include "GrGlyph.h" + +class GrAtlasMgr; +class GrFontCache; +class GrGpu; +class GrFontPurgeListener; + +/** + * The textcache maps a hostfontscaler instance to a dictionary of + * glyphid->strike + */ +class GrTextStrike { +public: + GrTextStrike(GrFontCache*, const GrKey* fontScalerKey, GrAtlasMgr*); + ~GrTextStrike(); + + const GrKey* getFontScalerKey() const { return fFontScalerKey; } + GrFontCache* getFontCache() const { return fFontCache; } + + inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*); + bool getGlyphAtlas(GrGlyph*, GrFontScaler*); + + // testing + int countGlyphs() const { return fCache.getArray().count(); } + const GrGlyph* glyphAt(int index) const { + return fCache.getArray()[index]; + } + GrAtlas* getAtlas() const { return fAtlas; } + +public: + // for LRU + GrTextStrike* fPrev; + GrTextStrike* fNext; + +private: + class Key; + GrTHashTable<GrGlyph, Key, 7> fCache; + const GrKey* fFontScalerKey; + GrTAllocPool<GrGlyph> fPool; + + GrFontCache* fFontCache; + GrAtlasMgr* fAtlasMgr; + GrAtlas* fAtlas; // linklist + + GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler); + // returns true if after the purge, the strike is empty + bool purgeAtlasAtY(GrAtlas* atlas, int yCoord); + + friend class GrFontCache; +}; + +class GrFontCache { +public: + GrFontCache(GrGpu*); + ~GrFontCache(); + + inline GrTextStrike* getStrike(GrFontScaler*); + + void freeAll(); + void abandonAll(); + + void purgeExceptFor(GrTextStrike*); + + // testing + int countStrikes() const { return fCache.getArray().count(); } + const GrTextStrike* strikeAt(int index) const { + return fCache.getArray()[index]; + } + GrTextStrike* getHeadStrike() const { return fHead; } + +#if GR_DEBUG + void validate() const; +#else + void validate() const {} +#endif + +private: + friend class GrFontPurgeListener; + + class Key; + GrTHashTable<GrTextStrike, Key, 8> fCache; + // for LRU + GrTextStrike* fHead; + GrTextStrike* fTail; + + GrGpu* fGpu; + GrAtlasMgr* fAtlasMgr; + + + GrTextStrike* generateStrike(GrFontScaler*, const Key&); + inline void detachStrikeFromList(GrTextStrike*); +}; + +#endif + diff --git a/gpu/include/GrTexture.h b/gpu/include/GrTexture.h new file mode 100644 index 0000000000..71a58e621b --- /dev/null +++ b/gpu/include/GrTexture.h @@ -0,0 +1,213 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTexture_DEFINED +#define GrTexture_DEFINED + +#include "GrRefCnt.h" + +class GrTexture; + +/** + * GrRenderTarget represents a 2D buffer of pixels that can be rendered to. + * A context's render target is set by setRenderTarget(). Render targets are + * created by a createTexture with the kRenderTarget_TextureFlag flag. + * Additionally, the rendering destination set in the underlying 3D API at the + * time of GrContext's creation can be retrieved by calling + * currentRenderTarget() after creation before any calles to setRenderTarget(). + */ +class GrRenderTarget : public GrRefCnt { +public: + /** + * @return the width of the rendertarget + */ + virtual uint32_t width() const = 0; + /** + * @return the height of the rendertarget + */ + virtual uint32_t height() const = 0; + + /** + * @return the texture associated with the rendertarget, may be NULL. + */ + GrTexture* asTexture() {return fTexture;} + +protected: + GrRenderTarget(GrTexture* texture) : fTexture(texture) {} + GrTexture* fTexture; +}; + +class GrTexture : public GrRefCnt { +public: + enum PixelConfig { + kUnknown_PixelConfig, + kAlpha_8_PixelConfig, + kIndex_8_PixelConfig, + kRGB_565_PixelConfig, + kRGBA_4444_PixelConfig, //!< premultiplied + kRGBA_8888_PixelConfig, //!< premultiplied + kRGBX_8888_PixelConfig, //!< treat the alpha channel as opaque + }; + static size_t BytesPerPixel(PixelConfig); + static bool PixelConfigIsOpaque(PixelConfig); + +protected: + GrTexture(uint32_t contentWidth, + uint32_t contentHeight, + uint32_t allocWidth, + uint32_t allocHeight, + PixelConfig config) : + fAllocWidth(allocWidth), + fAllocHeight(allocHeight), + fContentWidth(contentWidth), + fContentHeight(contentHeight), + fConfig(config) { + // only make sense if alloc size is pow2 + fShiftFixedX = 31 - Gr_clz(allocWidth); + fShiftFixedY = 31 - Gr_clz(allocHeight); + } +public: + virtual ~GrTexture(); + + /** + * Retrieves the width of the content area of the texture. Reflects the + * width passed to GrGpu::createTexture(). + * + * @return the width in texels + */ + uint32_t contentWidth() const { return fContentWidth; } + /** + * Retrieves the height of the content area of the texture. Reflects the + * height passed to GrGpu::createTexture(). + * + * @return the height in texels + */ + uint32_t contentHeight() const { return fContentHeight; } + + /** + * Retrieves the texture width actually allocated in texels. + * + * @return the width in texels + */ + uint32_t allocWidth() const { return fAllocWidth; } + /** + * Retrieves the texture height actually allocated in texels. + * + * @return the height in texels + */ + uint32_t allocHeight() const { return fAllocHeight; } + + /** + * Convert from texels to normalized texture coords for POT textures + * only. + */ + GrFixed normalizeFixedX(GrFixed x) const { GrAssert(GrIsPow2(fAllocWidth)); + return x >> fShiftFixedX; } + GrFixed normalizeFixedY(GrFixed y) const { GrAssert(GrIsPow2(fAllocHeight)); + return y >> fShiftFixedY; } + + /** + * Retrieves the pixel config specified when the texture was created. + */ + PixelConfig config() const { return fConfig; } + + /** + * The number of bytes used by the texture + */ + size_t sizeInBytes() const { + return fAllocWidth * fAllocHeight * BytesPerPixel(fConfig); + } + + /** + * Updates a subrectangle of texels in the texture. + * + * @param x left edge of rectangle to update + * @param y top edge of rectangle to update + * @param width width of rectangle to update + * @param height height of rectangle to update + * @param srcData width*height texels of data in same format that was used + * at texture creation. + */ + virtual void uploadTextureData(uint32_t x, + uint32_t y, + uint32_t width, + uint32_t height, + const void* srcData) = 0; + /** + * Indicates that GPU context in which this texture was created is destroyed + * and that Ganesh should not attempt to free the texture with the + * underlying API. + */ + virtual void abandon() = 0; + + /** + * Queries whether the texture was created as a render target. + * + * Use asRenderTarget() to use the texture as a render target if this + * returns true. + * + * @return true if the texture was created as a render target. + */ + virtual bool isRenderTarget() const = 0; + + /** + * Retrieves the render target underlying this texture that can be passed to + * GrGpu::setRenderTarget(). + * + * If isRenderTarget() is false then the returned handle is undefined. + * + * @return handle to render target or undefined if the texture is not a + * render target + */ + virtual GrRenderTarget* asRenderTarget() = 0; + + /** + * Removes the "rendertargetness" from a texture. This may or may not + * actually do anything with the underlying 3D API. + */ + virtual void removeRenderTarget() = 0; + + /** + * Return the native ID or handle to the texture, depending on the + * platform. e.g. on opengl, return the texture ID. + */ + virtual intptr_t getTextureHandle() = 0; + +#if GR_DEBUG + void validate() const { + this->INHERITED::validate(); + } +#else + void validate() const {} +#endif + +private: + uint32_t fAllocWidth; + uint32_t fAllocHeight; + uint32_t fContentWidth; + uint32_t fContentHeight; + // these two shift a fixed-point value into normalized coordinates + // for this texture if the texture is power of two sized. + int fShiftFixedX; + int fShiftFixedY; + PixelConfig fConfig; + + typedef GrRefCnt INHERITED; +}; + +#endif + diff --git a/gpu/include/GrTextureCache.h b/gpu/include/GrTextureCache.h new file mode 100644 index 0000000000..e3d4f0a100 --- /dev/null +++ b/gpu/include/GrTextureCache.h @@ -0,0 +1,289 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTextureCache_DEFINED +#define GrTextureCache_DEFINED + +#include "GrTypes.h" +#include "GrTHashCache.h" + +class GrTexture; + +// return true if a<b, or false if b<a +// +#define RET_IF_LT_OR_GT(a, b) \ + do { \ + if ((a) < (b)) { \ + return true; \ + } \ + if ((b) < (a)) { \ + return false; \ + } \ + } while (0) + +/** + * Helper class for GrTextureCache, the Key is used to identify src data for + * a texture. It is identified by 2 32bit data fields which can hold any + * data (uninterpreted by the cache) and a width/height. + */ +class GrTextureKey { +public: + enum { + kHashBits = 7, + kHashCount = 1 << kHashBits, + kHashMask = kHashCount - 1 + }; + + GrTextureKey(uint32_t p0, uint32_t p1, uint16_t width, uint16_t height) { + fP0 = p0; + fP1 = p1; + fP2 = width | (height << 16); + GR_DEBUGCODE(fHashIndex = -1); + } + + GrTextureKey(const GrTextureKey& src) { + fP0 = src.fP0; + fP1 = src.fP1; + fP2 = src.fP2; + finalize(src.fPrivateBits); + } + + //!< returns hash value [0..kHashMask] for the key + int hashIndex() const { return fHashIndex; } + + friend bool operator==(const GrTextureKey& a, const GrTextureKey& b) { + GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex); + return a.fP0 == b.fP0 && a.fP1 == b.fP1 && a.fP2 == b.fP2 && + a.fPrivateBits == b.fPrivateBits; + } + + friend bool operator!=(const GrTextureKey& a, const GrTextureKey& b) { + GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex); + return !(a == b); + } + + friend bool operator<(const GrTextureKey& a, const GrTextureKey& b) { + RET_IF_LT_OR_GT(a.fP0, b.fP0); + RET_IF_LT_OR_GT(a.fP1, b.fP1); + RET_IF_LT_OR_GT(a.fP2, b.fP2); + return a.fPrivateBits < b.fPrivateBits; + } + +private: + void finalize(uint32_t privateBits) { + fPrivateBits = privateBits; + this->computeHashIndex(); + } + + uint16_t width() const { return fP2 & 0xffff; } + uint16_t height() const { return (fP2 >> 16); } + + static uint32_t rol(uint32_t x) { + return (x >> 24) | (x << 8); + } + static uint32_t ror(uint32_t x) { + return (x >> 8) | (x << 24); + } + static uint32_t rohalf(uint32_t x) { + return (x >> 16) | (x << 16); + } + + void computeHashIndex() { + uint32_t hash = fP0 ^ rol(fP1) ^ ror(fP2) ^ rohalf(fPrivateBits); + // this way to mix and reduce hash to its index may have to change + // depending on how many bits we allocate to the index + hash ^= hash >> 16; + hash ^= hash >> 8; + fHashIndex = hash & kHashMask; + } + + uint32_t fP0; + uint32_t fP1; + uint32_t fP2; + uint32_t fPrivateBits; + + // this is computed from the fP... fields + int fHashIndex; + + friend class GrContext; +}; + +/////////////////////////////////////////////////////////////////////////////// + +class GrTextureEntry { +public: + GrTexture* texture() const { return fTexture; } + const GrTextureKey& key() const { return fKey; } + +#if GR_DEBUG + GrTextureEntry* next() const { return fNext; } + GrTextureEntry* prev() const { return fPrev; } +#endif + +#if GR_DEBUG + void validate() const; +#else + void validate() const {} +#endif + +private: + GrTextureEntry(const GrTextureKey& key, GrTexture* texture); + ~GrTextureEntry(); + + bool isLocked() const { return fLockCount != 0; } + void lock() { ++fLockCount; } + void unlock() { + GrAssert(fLockCount > 0); + --fLockCount; + } + + GrTextureKey fKey; + GrTexture* fTexture; + + // track if we're in use, used when we need to purge + // we only purge unlocked entries + int fLockCount; + + // we're a dlinklist + GrTextureEntry* fPrev; + GrTextureEntry* fNext; + + friend class GrTextureCache; +}; + +/////////////////////////////////////////////////////////////////////////////// + +#include "GrTHashCache.h" + +/** + * Cache of GrTexture objects. + * + * These have a corresponding GrTextureKey, built from 96bits identifying the + * texture/bitmap. + * + * The cache stores the entries in a double-linked list, which is its LRU. + * When an entry is "locked" (i.e. given to the caller), it is moved to the + * head of the list. If/when we must purge some of the entries, we walk the + * list backwards from the tail, since those are the least recently used. + * + * For fast searches, we maintain a sorted array (based on the GrTextureKey) + * which we can bsearch. When a new entry is added, it is inserted into this + * array. + * + * For even faster searches, a hash is computed from the Key. If there is + * a collision between two keys with the same hash, we fall back on the + * bsearch, and update the hash to reflect the most recent Key requested. + */ +class GrTextureCache { +public: + GrTextureCache(int maxCount, size_t maxBytes); + ~GrTextureCache(); // uses kFreeTexture_DeleteMode + + /** + * Search for an entry with the same Key. If found, "lock" it and return it. + * If not found, return null. + */ + GrTextureEntry* findAndLock(const GrTextureKey&); + + /** + * Create a new entry, based on the specified key and texture, and return + * its "locked" entry. + * + * Ownership of the texture is transferred to the Entry, which will unref() + * it when we are purged or deleted. + */ + GrTextureEntry* createAndLock(const GrTextureKey&, GrTexture*); + + /** + * Detach removes an entry from the cache. This prevents the entry from + * being found by a subsequent findAndLock() until it is reattached. The + * entry still counts against the cache's budget and should be reattached + * when exclusive access is no longer needed. + */ + void detach(GrTextureEntry*); + + /** + * Reattaches a texture to the cache and unlocks it. Allows it to be found + * by a subsequent findAndLock or be purged (provided its lock count is + * now 0.) + */ + void reattachAndUnlock(GrTextureEntry*); + + /** + * When done with an entry, call unlock(entry) on it, which returns it to + * a purgable state. + */ + void unlock(GrTextureEntry*); + + enum DeleteMode { + kFreeTexture_DeleteMode, + kAbandonTexture_DeleteMode + }; + void deleteAll(DeleteMode); + +#if GR_DEBUG + void validate() const; +#else + void validate() const {} +#endif + +private: + void internalDetach(GrTextureEntry*, bool); + void attachToHead(GrTextureEntry*, bool); + void purgeAsNeeded(); // uses kFreeTexture_DeleteMode + + class Key; + GrTHashTable<GrTextureEntry, Key, 8> fCache; + + // manage the dlink list + GrTextureEntry* fHead; + GrTextureEntry* fTail; + + // our budget, used in purgeAsNeeded() + const int fMaxCount; + const size_t fMaxBytes; + + // our current stats, related to our budget + int fEntryCount; + size_t fEntryBytes; + int fClientDetachedCount; + size_t fClientDetachedBytes; +}; + +/////////////////////////////////////////////////////////////////////////////// + +#if GR_DEBUG + class GrAutoTextureCacheValidate { + public: + GrAutoTextureCacheValidate(GrTextureCache* cache) : fCache(cache) { + cache->validate(); + } + ~GrAutoTextureCacheValidate() { + fCache->validate(); + } + private: + GrTextureCache* fCache; + }; +#else + class GrAutoTextureCacheValidate { + public: + GrAutoTextureCacheValidate(GrTextureCache*) {} + }; +#endif + +#endif + diff --git a/gpu/include/GrTouchGesture.h b/gpu/include/GrTouchGesture.h new file mode 100644 index 0000000000..03f970b246 --- /dev/null +++ b/gpu/include/GrTouchGesture.h @@ -0,0 +1,56 @@ +#ifndef GrTouchGesture_DEFINED +#define GrTouchGesture_DEFINED + +#include "GrTypes.h" +#include "SkTDArray.h" +#include "SkMatrix.h" + +#include "FlingState.h" + +class GrTouchGesture { +public: + GrTouchGesture(); + ~GrTouchGesture(); + + void touchBegin(void* owner, float x, float y); + void touchMoved(void* owner, float x, float y); + void touchEnd(void* owner); + void reset(); + + const SkMatrix& localM(); + const SkMatrix& globalM() const { return fGlobalM; } + +private: + enum State { + kEmpty_State, + kTranslate_State, + kZoom_State, + }; + + struct Rec { + void* fOwner; + float fStartX, fStartY; + float fPrevX, fPrevY; + float fLastX, fLastY; + SkMSec fPrevT, fLastT; + }; + SkTDArray<Rec> fTouches; + + State fState; + SkMatrix fLocalM, fGlobalM; + FlingState fFlinger; + SkMSec fLastUpT; + SkPoint fLastUpP; + + + void flushLocalM(); + int findRec(void* owner) const; + void appendNewRec(void* owner, float x, float y); + float computePinch(const Rec&, const Rec&); + float limitTotalZoom(float scale) const; + bool handleDblTap(float, float); +}; + +#endif + + diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h new file mode 100644 index 0000000000..a491295192 --- /dev/null +++ b/gpu/include/GrTypes.h @@ -0,0 +1,142 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrTypes_DEFINED +#define GrTypes_DEFINED + +#include "GrConfig.h" + +#include <memory.h> +#include <string.h> + +/** + * Macro to round n up to the next multiple of 4, or return it unchanged if + * n is already a multiple of 4 + */ +#define GrALIGN4(n) (((n) + 3) >> 2 << 2) +#define GrIsALIGN4(n) (((n) & 3) == 0) + +template <typename T> const T& GrMin(const T& a, const T& b) { + return (a < b) ? a : b; +} + +template <typename T> const T& GrMax(const T& a, const T& b) { + return (b < a) ? a : b; +} + +// compile time versions of min/max +#define GR_CT_MAX(a, b) (((b) < (a)) ? (a) : (b)) +#define GR_CT_MIN(a, b) (((b) < (a)) ? (b) : (a)) + +/** + * divide, rounding up + */ +inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) { + return (x + (y-1)) / y; +} + +/** + * align up + */ +inline uint32_t GrUIAlignUp(uint32_t x, uint32_t alignment) { + return GrUIDivRoundUp(x, alignment) * alignment; +} + +/** + * amount of pad needed to align up + */ +inline uint32_t GrUIAlignUpPad(uint32_t x, uint32_t alignment) { + return (alignment - x % alignment) % alignment; +} + +/** + * align down + */ +inline uint32_t GrUIAlignDown(uint32_t x, uint32_t alignment) { + return (x / alignment) * alignment; +} + +/** + * Count elements in an array + */ +#define GR_ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) + +//!< allocate a block of memory, will never return NULL +extern void* GrMalloc(size_t bytes); + +//!< free block allocated by GrMalloc. ptr may be NULL +extern void GrFree(void* ptr); + +static inline void Gr_bzero(void* dst, size_t size) { + memset(dst, 0, size); +} + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Return the number of leading zeros in n + */ +extern int Gr_clz(uint32_t n); + +/** + * Return true if n is a power of 2 + */ +static inline bool GrIsPow2(unsigned n) { + return n && 0 == (n & (n - 1)); +} + +/** + * Return the next power of 2 >= n. + */ +static inline uint32_t GrNextPow2(uint32_t n) { + return n ? (1 << (32 - Gr_clz(n - 1))) : 1; +} + +/////////////////////////////////////////////////////////////////////////////// + +/** + * 16.16 fixed point type + */ +typedef int32_t GrFixed; + +#if GR_DEBUG + +static inline int16_t GrToS16(intptr_t x) { + GrAssert((int16_t)x == x); + return (int16_t)x; +} + +#else + +#define GrToS16(x) x + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Type used to describe format of vertices in arrays + * Values are defined in GrDrawTarget + */ +typedef uint16_t GrVertexLayout; + +/////////////////////////////////////////////////////////////////////////////// + +// this is included only to make it easy to use this debugging facility +#include "GrInstanceCounter.h" + +#endif diff --git a/gpu/include/GrUserConfig.h b/gpu/include/GrUserConfig.h new file mode 100644 index 0000000000..2e6f3919d6 --- /dev/null +++ b/gpu/include/GrUserConfig.h @@ -0,0 +1,57 @@ +#ifndef GrUserConfig_DEFINED +#define GrUserConfig_DEFINED + +#if defined(GR_USER_CONFIG_FILE) + #error "default user config pulled in but GR_USER_CONFIG_FILE is defined." +#endif + +#if 0 + #undef GR_RELEASE + #undef GR_DEBUG + #define GR_RELEASE 0 + #define GR_DEBUG 1 +#endif + +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +//#define GR_FORCE_GLCHECKERR 1 + +/* + * The default 32bit pixel config for texture upload is GL_RGBA. If your + * bitmaps map to a different GL enum, specify that with this define. + */ +//#define SK_GL_32BPP_COLOR_FORMAT GL_RGBA + +/* + * To diagnose texture cache performance, define this to 1 if you want to see + * a log statement everytime we upload an image to create a texture. + */ +//#define GR_DUMP_TEXTURE_UPLOAD 1 + +//////////////////////////////////////////////////////////////////////////////// +// Decide Ganesh types + +#define GR_SCALAR_IS_FIXED 0 +#define GR_SCALAR_IS_FLOAT 1 + +#define GR_TEXT_SCALAR_IS_USHORT 0 +#define GR_TEXT_SCALAR_IS_FIXED 0 +#define GR_TEXT_SCALAR_IS_FLOAT 1 + +#endif + + diff --git a/gpu/include/GrVertexBuffer.h b/gpu/include/GrVertexBuffer.h new file mode 100644 index 0000000000..5e83de95d5 --- /dev/null +++ b/gpu/include/GrVertexBuffer.h @@ -0,0 +1,92 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrVertexBuffer_DEFINED +#define GrVertexBuffer_DEFINED + +#include "GrRefCnt.h" + +class GrVertexBuffer : public GrRefCnt { +protected: + GrVertexBuffer(uint32_t sizeInBytes, bool dynamic) : + fSizeInBytes(sizeInBytes), + fDynamic(dynamic) {} +public: + virtual ~GrVertexBuffer() {} + + /** + Retrieves the size of the vertex buffer + + @return the size of the vertex buffer in bytes + */ + uint32_t size() { return fSizeInBytes; } + + /** + Retrieves whether the vertex buffer was created with the dynamic flag + + @return true if the vertex buffer was created with the dynamic flag + */ + bool dynamic() const { return fDynamic; } + + /** + Indicates that GPU context in which this veretx buffer was created is + destroyed and that Ganesh should not attempt to free the texture with the + underlying API. + */ + virtual void abandon() = 0; + + /** + Locks the vertex buffer to be written by the CPU. + + The previous content of the vertex buffer is invalidated. It is an error to + draw whil the buffer is locked. It is an error to call lock on an already + locked vertex buffer. + + @return a pointer to the vertex data or NULL if the lock fails. + */ + virtual void* lock() = 0; + + /** + Unlocks the vertex buffer. + + The pointer returned by the previous lock call will no longer be valid. + */ + virtual void unlock() = 0; + + /** + Queries whether the vertex buffer has been locked. + + @return true if the vertex buffer is locked, false otherwise. + */ + virtual bool isLocked() const = 0; + + /** + Updates the vertex buffer data. + + The size of the vertex buffer will be preserved. However, only the updated + region will have defined contents. + + @return returns true if the update succeeds, false otherwise. + */ + virtual bool updateData(const void* src, uint32_t srcSizeInBytes) = 0; + +private: + uint32_t fSizeInBytes; + bool fDynamic; +}; + +#endif diff --git a/gpu/include/GrVertexBufferAllocPool.h b/gpu/include/GrVertexBufferAllocPool.h new file mode 100644 index 0000000000..6a781aa344 --- /dev/null +++ b/gpu/include/GrVertexBufferAllocPool.h @@ -0,0 +1,141 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrVertexBufferAllocPool_DEFINED +#define GrVertexBufferAllocPool_DEFINED + +#include "GrNoncopyable.h" +#include "GrTDArray.h" +#include "GrTArray.h" + +class GrVertexBuffer; +class GrGpu; + +/** + * A pool of vertices in vertex buffers tied to a GrGpu. + * + * The pool has an alloc() function that returns a pointer into a locked + * vertex buffer. A client can release() if it has over-allocated. + * + * At creation time a minimum VB size can be specified. Additionally, + * a number of vertex buffers to preallocate can be specified. These will + * be allocated at the min size and kept until the pool is destroyed. + */ +class GrVertexBufferAllocPool : GrNoncopyable { +public: + /** + * Constructor + * + * @param gpu The GrGpu used to create the vertex buffers. + * @param bufferSize The size of created VBs (unless an alloc request + * exceeds this size in which case a larger VB is + * created). This value is clamped to some + * reasonable minimum. + * @param preallocBufferCnt The pool will allocate this number of VBs at + * bufferSize and keep them until it is destroyed. + */ + GrVertexBufferAllocPool(GrGpu* gpu, + size_t bufferSize = 0, + int preallocBufferCnt = 0); + ~GrVertexBufferAllocPool(); + + /** + * Ensures all VBs are unlocked. Call before using to draw. + */ + void unlock(); + + /** + * Frees all vertex data that has been allocated with alloc(). + */ + void reset(); + + /** + * Returns a block of memory bytes size big. The vertex buffer + * containing the memory is returned in buffer. + * + * @param layout specifies type of vertices to allocate space for + * @param vertexCount number of vertices to allocate space for + * @param buffer returns the vertex buffer that will hold the + * vertices. + * @param startVertex returns the offset into buffer of the first vertex. + * In units of the size of a vertex using layout param. + * @return pointer to first vertex. + */ + void* alloc(GrVertexLayout layout, + uint32_t vertexCount, + GrVertexBuffer** buffer, + uint32_t* startVertex); + + /** + * Gets the number of vertices that can be allocated without changing VBs. + * This means either the last VB returned by alloc() if the last alloc did + * not exhaust it. If that VB was exhausted by the last alloc or alloc hasn't + * been called since reset() then it will be the number of vertices that + * would fit in an available preallocated VB. If no preallocated VB + * is available then it returns 0 since the next alloc would force a new + * VB to be created. + */ + int currentBufferVertices(GrVertexLayout layout) const; + + /** + * Gets the number of preallocated buffers that are yet to be used. + */ + int preallocatedBuffersRemaining() const; + + /** + * Gets the number of vertices that can fit in a preallocated vertex buffer. + * Zero if no preallocated buffers. + */ + int preallocatedBufferVertices(GrVertexLayout layout) const; + + /** + * gets the number of preallocated vertex buffers + */ + int preallocatedBufferCount() const; + + + /** + * Releases the most recently allocated bytes back to the pool. + */ + void release(size_t bytes); + + /** + * Gets the GrGpu that this pool is associated with. + */ + GrGpu* getGpu() { return fGpu; } + + +private: + struct BufferBlock { + size_t fBytesFree; + GrVertexBuffer* fVertexBuffer; + }; + + bool createBlock(size_t size); + void destroyBlock(); + + GrTArray<BufferBlock> fBlocks; + GrTDArray<GrVertexBuffer*> fPreallocBuffers; + int fPreallocBuffersInUse; + int fFirstPreallocBuffer; + + size_t fMinBlockSize; + GrGpu* fGpu; + void* fBufferPtr; +}; + +#endif diff --git a/gpu/include/SkGpuCanvas.h b/gpu/include/SkGpuCanvas.h new file mode 100644 index 0000000000..e8e6e7ae10 --- /dev/null +++ b/gpu/include/SkGpuCanvas.h @@ -0,0 +1,72 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkGpuCanvas_DEFINED +#define SkGpuCanvas_DEFINED + +#include "SkCanvas.h" + +class GrContext; + +/** + * Subclass of canvas that creates devices compatible with the GrContext pass + * to the canvas' constructor. + */ +class SkGpuCanvas : public SkCanvas { +public: + /** + * The GrContext object is reference counted. When passed to our + * constructor, its reference count is incremented. In our destructor, the + * GrGpu's reference count will be decremented. + */ + explicit SkGpuCanvas(GrContext*); + virtual ~SkGpuCanvas(); + + /** + * Return our GrContext instance + */ + GrContext* context() const { return fContext; } + + /** + * Override from SkCanvas. Returns true, and if not-null, sets size to + * be the width/height of our viewport. + */ + virtual bool getViewport(SkIPoint* size) const; + + /** + * Override from SkCanvas. Returns a new device of the correct subclass, + * as determined by the GrGpu passed to our constructor. + */ + virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, + bool isOpaque, bool isLayer); + +#if 0 + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, + SaveFlags flags = kARGB_ClipLayer_SaveFlag) { + return this->save(flags); + } +#endif + +private: + GrContext* fContext; + + typedef SkCanvas INHERITED; +}; + +#endif + + diff --git a/gpu/include/SkGr.h b/gpu/include/SkGr.h new file mode 100644 index 0000000000..4e9801f699 --- /dev/null +++ b/gpu/include/SkGr.h @@ -0,0 +1,238 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkGr_DEFINED +#define SkGr_DEFINED + +#include <stddef.h> + +// tetrark headers +#include "GrConfig.h" +#include "GrContext.h" +#include "GrFontScaler.h" +#include "GrPathIter.h" +#include "GrClipIterator.h" + +// skia headers +#include "SkBitmap.h" +#include "SkPath.h" +#include "SkPoint.h" +#include "SkRegion.h" +#include "SkShader.h" + +#if (GR_DEBUG && defined(SK_RELEASE)) || (GR_RELEASE && defined(SK_DEBUG)) +// #error "inconsistent GR_DEBUG and SK_DEBUG" +#endif + +#if GR_SCALAR_IS_FIXED + #ifdef SK_SCALAR_IS_FIXED + #define SK_SCALAR_IS_GR_SCALAR 1 + #else + #define SK_SCALAR_IS_GR_SCALAR 0 + #endif + #define SkScalarToGrScalar(x) SkScalarToFixed(x) + +#elif GR_SCALAR_IS_FLOAT + + #ifdef SK_SCALAR_IS_FLOAT + #define SK_SCALAR_IS_GR_SCALAR 1 + #else + #define SK_SCALAR_IS_GR_SCALAR 0 + #endif + #define SkScalarToGrScalar(x) SkScalarToFloat(x) + +#else + #error "Ganesh scalar type not defined" +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Sk to Gr Type conversions + +// Verify that SkPoint and GrPoint are compatible if using the same scalar type +#if 0/*SK_SCALAR_IS_GR_SCALAR*/ + GR_STATIC_ASSERT(sizeof(SkPoint) == sizeof(GrPoint)); + GR_STATIC_ASSERT(offsetof(SkPoint,fX) == offsetof(GrPoint,fX))); + GR_STATIC_ASSERT(offsetof(SkPoint,fY) == offsetof(GrPoint,fY))); +#endif + +GR_STATIC_ASSERT((int)GrSamplerState::kClamp_WrapMode == (int)SkShader::kClamp_TileMode); +GR_STATIC_ASSERT((int)GrSamplerState::kRepeat_WrapMode ==( + int)SkShader::kRepeat_TileMode); +GR_STATIC_ASSERT((int)GrSamplerState::kMirror_WrapMode == + (int)SkShader::kMirror_TileMode); + +#define sk_tile_mode_to_grwrap(X) ((GrSamplerState::WrapMode)(X)) + +GR_STATIC_ASSERT((int)GrGpu::kZero_BlendCoeff == (int)SkXfermode::kZero_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kOne_BlendCoeff == (int)SkXfermode::kOne_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kSC_BlendCoeff == (int)SkXfermode::kSC_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kISC_BlendCoeff == (int)SkXfermode::kISC_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kDC_BlendCoeff == (int)SkXfermode::kDC_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kIDC_BlendCoeff == (int)SkXfermode::kIDC_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kSA_BlendCoeff == (int)SkXfermode::kSA_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kISA_BlendCoeff == (int)SkXfermode::kISA_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kDA_BlendCoeff == (int)SkXfermode::kDA_Coeff); +GR_STATIC_ASSERT((int)GrGpu::kIDA_BlendCoeff == (int)SkXfermode::kIDA_Coeff); + +#define sk_blend_to_grblend(X) ((GrGpu::BlendCoeff)(X)) + +GR_STATIC_ASSERT((int)SkPath::kMove_Verb == (int)GrPathIter::kMove_Command); +GR_STATIC_ASSERT((int)SkPath::kLine_Verb == (int)GrPathIter::kLine_Command); +GR_STATIC_ASSERT((int)SkPath::kQuad_Verb == (int)GrPathIter::kQuadratic_Command); +GR_STATIC_ASSERT((int)SkPath::kCubic_Verb == (int)GrPathIter::kCubic_Command); +GR_STATIC_ASSERT((int)SkPath::kClose_Verb == (int)GrPathIter::kClose_Command); +GR_STATIC_ASSERT((int)SkPath::kDone_Verb == (int)GrPathIter::kEnd_Command); + +#define sk_path_verb_to_gr_path_command(X) ((GrPathIter::Command)(X)) + +/////////////////////////////////////////////////////////////////////////////// + +#include "SkColorPriv.h" + +static inline GrRect Sk2Gr(const SkRect& src) { + return GrRect(SkScalarToGrScalar(src.fLeft), + SkScalarToGrScalar(src.fTop), + SkScalarToGrScalar(src.fRight), + SkScalarToGrScalar(src.fBottom)); +} + +class SkGr { +public: + static inline SkIRect& SetIRect(SkIRect* dst, const GrIRect& src) { + GR_STATIC_ASSERT(sizeof(*dst) == sizeof(src)); + memcpy(dst, &src, sizeof(*dst)); + return *dst; + } + + static inline GrIRect& SetIRect(GrIRect* dst, const SkIRect& src) { + GR_STATIC_ASSERT(sizeof(*dst) == sizeof(src)); + memcpy(dst, &src, sizeof(*dst)); + return *dst; + } + + /** + * Convert the SkBitmap::Config to the corresponding PixelConfig, or + * kUnknown_PixelConfig if the conversion cannot be done. + */ + static GrTexture::PixelConfig BitmapConfig2PixelConfig(SkBitmap::Config, + bool isOpaque); + + static GrTexture::PixelConfig Bitmap2PixelConfig(const SkBitmap& bm) { + return BitmapConfig2PixelConfig(bm.config(), bm.isOpaque()); + } + + static void SkMatrix2GrMatrix(const SkMatrix& m, GrMatrix* g) { + g->setAll(SkScalarToGrScalar(m[0]), + SkScalarToGrScalar(m[1]), + SkScalarToGrScalar(m[2]), + SkScalarToGrScalar(m[3]), + SkScalarToGrScalar(m[4]), + SkScalarToGrScalar(m[5]), + SkScalarToGrScalar(m[6]), + SkScalarToGrScalar(m[7]), + SkScalarToGrScalar(m[8])); + } + + static GrColor SkColor2GrColor(SkColor c) { + SkPMColor pm = SkPreMultiplyColor(c); + unsigned r = SkGetPackedR32(pm); + unsigned g = SkGetPackedG32(pm); + unsigned b = SkGetPackedB32(pm); + unsigned a = SkGetPackedA32(pm); + return GrColorPackRGBA(r, g, b, a); + } + + /** + * This abandons all texture caches (for bitmaps and text) associated with + * the gpu, and frees any associated skia caches. It differs from + * deleteAllTextures in that it assumes that the gpu has lots its context, + * and thus the associated HW textures are no longer valid + */ + static void AbandonAllTextures(GrContext*); +}; + +//////////////////////////////////////////////////////////////////////////////// +// Classes + +class SkGrPathIter : public GrPathIter { +public: + SkGrPathIter(const SkPath& path) : fIter(path, false), fPath(path) {} + virtual Command next(GrPoint pts[]); + virtual Command next(); + virtual void rewind(); + virtual ConvexHint hint() const; +private: + +#if !SK_SCALAR_IS_GR_SCALAR + SkPoint fPoints[4]; +#endif + SkPath::Iter fIter; + const SkPath& fPath; +}; + +class SkGrClipIterator : public GrClipIterator { +public: + void reset(const SkRegion& clip) { + fIter.reset(clip); + this->invalidateBoundsCache(); + } + + // overrides + + virtual bool isDone() { return fIter.done(); } + virtual void getRect(GrIRect* rect) { + SkGr::SetIRect(rect, fIter.rect()); + } + virtual void next() { fIter.next(); } + virtual void rewind() { fIter.rewind(); } + virtual void computeBounds(GrIRect* bounds); + +private: + SkRegion::Iterator fIter; +}; + +class SkGlyphCache; + +class SkGrFontScaler : public GrFontScaler { +public: + explicit SkGrFontScaler(SkGlyphCache* strike); + virtual ~SkGrFontScaler(); + + // overrides + virtual const GrKey* getKey(); + virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds); + virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height, + int rowBytes, void* image); + virtual bool getGlyphPath(uint16_t glyphID, GrPath*); + +private: + SkGlyphCache* fStrike; + GrKey* fKey; +// DECLARE_INSTANCE_COUNTER(SkGrFontScaler); +}; + +//////////////////////////////////////////////////////////////////////////////// +// Helper functions + +GrTextureEntry* sk_gr_create_bitmap_texture(GrContext* ctx, + GrTextureKey* key, + const GrSamplerState& sampler, + const SkBitmap& bitmap); + +void sk_gr_set_paint(GrContext* ctx, const SkPaint& paint, bool justAlpha = false); + +#endif diff --git a/gpu/include/SkGrTexturePixelRef.h b/gpu/include/SkGrTexturePixelRef.h new file mode 100644 index 0000000000..1f5133f86d --- /dev/null +++ b/gpu/include/SkGrTexturePixelRef.h @@ -0,0 +1,50 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkGrTexturePixelRef_DEFINED +#define SkGrTexturePixelRef_DEFINED + +#include "SkPixelRef.h" +#include "GrGpu.h" + +class SkGrTexturePixelRef : public SkPixelRef { +public: + SkGrTexturePixelRef(GrTexture*); + virtual ~SkGrTexturePixelRef(); + + // override from SkPixelRef + virtual SkGpuTexture* getTexture() { return (SkGpuTexture*)fTexture; } + +protected: + // override from SkPixelRef + virtual void* onLockPixels(SkColorTable** ptr) { + if (ptr) { + *ptr = NULL; + } + return NULL; + } + + // override from SkPixelRef + virtual void onUnlockPixels() {} + +private: + GrTexture* fTexture; + typedef SkPixelRef INHERITED; +}; + +#endif + diff --git a/gpu/include/SkUIView.h b/gpu/include/SkUIView.h new file mode 100644 index 0000000000..5e12e004d6 --- /dev/null +++ b/gpu/include/SkUIView.h @@ -0,0 +1,64 @@ +#import <UIKit/UIKit.h> + +#include "SkMatrix.h" +#include "FlingState.h" + +#import <OpenGLES/EAGL.h> +#import <OpenGLES/ES1/gl.h> +#import <OpenGLES/ES1/glext.h> + +class SkOSWindow; +class SkEvent; + +@interface SkUIView : UIView <UIAccelerometerDelegate> { + BOOL fRedrawRequestPending; + SkOSWindow* fWind; + SkMatrix fMatrix, fLocalMatrix; + bool fNeedGestureEnded; + + SkMatrix fRotateMatrix; + + float fFirstPinchX, fFirstPinchY; + bool fNeedFirstPinch; + + float fZoomAroundX, fZoomAroundY; + bool fZoomAround; + + FlingState fFlingState; + + GrAnimateFloat fWarpState; + bool fUseWarp; + + struct { + EAGLContext* fContext; + GLuint fRenderbuffer; + GLuint fStencilbuffer; + GLuint fFramebuffer; + GLint fWidth; + GLint fHeight; + } fGL; + + UILabel* fTitleLabel; + + enum Backend { + kGL_Backend, + kRaster_Backend, + }; + + // these are visible to DetailViewController + Backend fBackend; + bool fComplexClip; +} + +@property (nonatomic, assign) SkOSWindow *fWind; +@property (nonatomic, retain) UILabel* fTitleLabel; +@property (nonatomic, assign) Backend fBackend; +@property (nonatomic, assign) bool fComplexClip; +@property (nonatomic, assign, setter=setWarpState) bool fUseWarp; + +- (void)setSkTitle:(const char*)title; +- (void)postInvalWithRect:(const SkIRect*)rectOrNil; +- (BOOL)onHandleEvent:(const SkEvent&)event; + +@end + |