don't reallocate the mesh each time we use it

the Mesh object can be part of each Layer (at least currently).
also reworked the Mesh code a bit to make it easier to access
the vertex data.

Change-Id: I0490851ba898f0aa2e55b62958dcd8bdb535e98b
This commit is contained in:
Mathias Agopian 2013-08-13 20:51:23 -07:00
parent 3f84483382
commit 5cdc8994a0
7 changed files with 87 additions and 55 deletions

View File

@ -74,6 +74,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
mFrameLatencyNeeded(false), mFrameLatencyNeeded(false),
mFiltering(false), mFiltering(false),
mNeedsFiltering(false), mNeedsFiltering(false),
mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
mSecure(false), mSecure(false),
mProtectedByApp(false), mProtectedByApp(false),
mHasSurface(false), mHasSurface(false),
@ -494,9 +495,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip, void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
float red, float green, float blue, float alpha) const float red, float green, float blue, float alpha) const
{ {
Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); computeGeometry(hw, mMesh);
computeGeometry(hw, mesh); mFlinger->getRenderEngine().fillWithColor(mMesh, red, green, blue, alpha);
mFlinger->getRenderEngine().fillWithColor(mesh, red, green, blue, alpha);
} }
void Layer::clearWithOpenGL( void Layer::clearWithOpenGL(
@ -509,8 +509,7 @@ void Layer::drawWithOpenGL(
const uint32_t fbHeight = hw->getHeight(); const uint32_t fbHeight = hw->getHeight();
const State& s(getDrawingState()); const State& s(getDrawingState());
Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2); computeGeometry(hw, mMesh);
computeGeometry(hw, mesh);
/* /*
* NOTE: the way we compute the texture coordinates here produces * NOTE: the way we compute the texture coordinates here produces
@ -535,20 +534,19 @@ void Layer::drawWithOpenGL(
// TODO: we probably want to generate the texture coords with the mesh // TODO: we probably want to generate the texture coords with the mesh
// here we assume that we only have 4 vertices // here we assume that we only have 4 vertices
size_t stride = mesh.getStride(); Mesh::VertexArray texCoords(mMesh.getTexCoordArray());
float* base = mesh.getTexCoords(); texCoords[0].s = left;
base[stride*0 + 0] = left; texCoords[0].t = 1.0f - top;
base[stride*0 + 1] = 1.0f - top; texCoords[1].s = left;
base[stride*1 + 0] = left; texCoords[1].t = 1.0f - bottom;
base[stride*1 + 1] = 1.0f - bottom; texCoords[2].s = right;
base[stride*2 + 0] = right; texCoords[2].t = 1.0f - bottom;
base[stride*2 + 1] = 1.0f - bottom; texCoords[3].s = right;
base[stride*3 + 0] = right; texCoords[3].t = 1.0f - top;
base[stride*3 + 1] = 1.0f - top;
RenderEngine& engine(mFlinger->getRenderEngine()); RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha);
engine.drawMesh(mesh); engine.drawMesh(mMesh);
engine.disableBlending(); engine.disableBlending();
} }
@ -596,12 +594,13 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh) const
// subtract the transparent region and snap to the bounds // subtract the transparent region and snap to the bounds
win = reduce(win, s.activeTransparentRegion); win = reduce(win, s.activeTransparentRegion);
tr.transform(mesh[0], win.left, win.top); Mesh::VertexArray position(mesh.getPositionArray());
tr.transform(mesh[1], win.left, win.bottom); tr.transform(position[0], win.left, win.top);
tr.transform(mesh[2], win.right, win.bottom); tr.transform(position[1], win.left, win.bottom);
tr.transform(mesh[3], win.right, win.top); tr.transform(position[2], win.right, win.bottom);
tr.transform(position[3], win.right, win.top);
for (size_t i=0 ; i<4 ; i++) { for (size_t i=0 ; i<4 ; i++) {
mesh[i][1] = hw_h - mesh[i][1]; position[i].y = hw_h - position[i].y;
} }
} }

View File

@ -357,6 +357,8 @@ private:
bool mFiltering; bool mFiltering;
// Whether filtering is needed b/c of the drawingstate // Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering; bool mNeedsFiltering;
// The mesh used to draw the layer in GLES composition mode
mutable Mesh mMesh;
// page-flip thread (currently main thread) // page-flip thread (currently main thread)
bool mSecure; // no screenshots bool mSecure; // no screenshots

View File

@ -192,7 +192,7 @@ void GLES11RenderEngine::fillWithColor(const Mesh& mesh, float r, float g, float
glVertexPointer(mesh.getVertexSize(), glVertexPointer(mesh.getVertexSize(),
GL_FLOAT, GL_FLOAT,
mesh.getByteStride(), mesh.getByteStride(),
mesh.getVertices()); mesh.getPositions());
glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
} }
@ -209,7 +209,7 @@ void GLES11RenderEngine::drawMesh(const Mesh& mesh) {
glVertexPointer(mesh.getVertexSize(), glVertexPointer(mesh.getVertexSize(),
GL_FLOAT, GL_FLOAT,
mesh.getByteStride(), mesh.getByteStride(),
mesh.getVertices()); mesh.getPositions());
glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());

View File

@ -168,7 +168,7 @@ void GLES20RenderEngine::fillWithColor(const Mesh& mesh, float r, float g, float
mesh.getVertexSize(), mesh.getVertexSize(),
GL_FLOAT, GL_FALSE, GL_FLOAT, GL_FALSE,
mesh.getByteStride(), mesh.getByteStride(),
mesh.getVertices()); mesh.getPositions());
glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
} }
@ -190,7 +190,7 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
mesh.getVertexSize(), mesh.getVertexSize(),
GL_FLOAT, GL_FALSE, GL_FLOAT, GL_FALSE,
mesh.getByteStride(), mesh.getByteStride(),
mesh.getVertices()); mesh.getPositions());
glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());

View File

@ -30,23 +30,15 @@ Mesh::~Mesh() {
delete [] mVertices; delete [] mVertices;
} }
float const* Mesh::operator[](size_t index) const {
return &mVertices[index * mStride];
}
float* Mesh::operator[](size_t index) {
return &mVertices[index * mStride];
}
Mesh::Primitive Mesh::getPrimitive() const { Mesh::Primitive Mesh::getPrimitive() const {
return mPrimitive; return mPrimitive;
} }
float const* Mesh::getVertices() const { float const* Mesh::getPositions() const {
return mVertices; return mVertices;
} }
float* Mesh::getVertices() { float* Mesh::getPositions() {
return mVertices; return mVertices;
} }

View File

@ -24,34 +24,72 @@ namespace android {
class Mesh { class Mesh {
public: public:
enum Primitive { enum Primitive {
TRIANGLES = 0x0004, TRIANGLES = 0x0004, // GL_TRIANGLES
TRIANGLE_STRIP = 0x0005, TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP
TRIANGLE_FAN = 0x0006 TRIANGLE_FAN = 0x0006 // GL_TRIANGLE_FAN
}; };
Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0); Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0);
~Mesh(); ~Mesh();
float const* operator[](size_t index) const; /*
float* operator[](size_t index); * VertexArray handles the stride automatically. It also provides
* a convenient way to set position and texture coordinates by using
* the usual x,y,z,w or s,t,r,q names.
*/
class VertexArray {
friend class Mesh;
float* mData;
size_t mStride;
VertexArray(float* data, size_t stride) : mData(data), mStride(stride) { }
public:
struct vertexData {
operator float*() { return reinterpret_cast<float*>(this); }
union {
struct { float x, y, z, w; };
struct { float s, t, r, q; };
};
};
vertexData& operator[](size_t index) {
return *reinterpret_cast<vertexData*>(&mData[index*mStride]); }
vertexData const& operator[](size_t index) const {
return *reinterpret_cast<vertexData const*>(&mData[index*mStride]); }
};
VertexArray getPositionArray() { return VertexArray(getPositions(), mStride); }
VertexArray getTexCoordArray() { return VertexArray(getTexCoords(), mStride); }
Primitive getPrimitive() const; Primitive getPrimitive() const;
float const* getVertices() const; // returns a pointer to the vertices positions
float* getVertices(); float const* getPositions() const;
// returns a pointer to the vertices texture coordinates
float const* getTexCoords() const; float const* getTexCoords() const;
float* getTexCoords();
// number of vertices in this mesh
size_t getVertexCount() const; size_t getVertexCount() const;
// dimension of vertices
size_t getVertexSize() const; size_t getVertexSize() const;
// dimension of texture coordinates
size_t getTexCoordsSize() const; size_t getTexCoordsSize() const;
// return stride in bytes
size_t getByteStride() const; size_t getByteStride() const;
// return stride in floats
size_t getStride() const; size_t getStride() const;
private: private:
Mesh(const Mesh&);
Mesh& operator = (const Mesh&);
Mesh const& operator = (const Mesh&) const;
float* getPositions();
float* getTexCoords();
float* mVertices; float* mVertices;
size_t mVertexCount; size_t mVertexCount;
size_t mVertexSize; size_t mVertexSize;

View File

@ -149,19 +149,20 @@ void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
size_t c; size_t c;
Rect const* r = region.getArray(&c); Rect const* r = region.getArray(&c);
Mesh mesh(Mesh::TRIANGLES, c*6, 2); Mesh mesh(Mesh::TRIANGLES, c*6, 2);
Mesh::VertexArray position(mesh.getPositionArray());
for (size_t i=0 ; i<c ; i++, r++) { for (size_t i=0 ; i<c ; i++, r++) {
mesh[i*6 + 0][0] = r->left; position[i*6 + 0].x = r->left;
mesh[i*6 + 0][1] = height - r->top; position[i*6 + 0].y = height - r->top;
mesh[i*6 + 1][0] = r->left; position[i*6 + 1].x = r->left;
mesh[i*6 + 1][1] = height - r->bottom; position[i*6 + 1].y = height - r->bottom;
mesh[i*6 + 2][0] = r->right; position[i*6 + 2].x = r->right;
mesh[i*6 + 2][1] = height - r->bottom; position[i*6 + 2].y = height - r->bottom;
mesh[i*6 + 3][0] = r->left; position[i*6 + 3].x = r->left;
mesh[i*6 + 3][1] = height - r->top; position[i*6 + 3].y = height - r->top;
mesh[i*6 + 4][0] = r->right; position[i*6 + 4].x = r->right;
mesh[i*6 + 4][1] = height - r->bottom; position[i*6 + 4].y = height - r->bottom;
mesh[i*6 + 5][0] = r->right; position[i*6 + 5].x = r->right;
mesh[i*6 + 5][1] = height - r->top; position[i*6 + 5].y = height - r->top;
} }
fillWithColor(mesh, red, green, blue, alpha); fillWithColor(mesh, red, green, blue, alpha);
} }