2009-03-04 03:31:44 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <utils/Errors.h>
|
|
|
|
#include <utils/Log.h>
|
2009-05-22 08:27:01 +00:00
|
|
|
#include <binder/IPCThreadState.h>
|
|
|
|
#include <binder/IServiceManager.h>
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
#include <GLES/gl.h>
|
|
|
|
#include <GLES/glext.h>
|
|
|
|
|
|
|
|
#include <hardware/hardware.h>
|
|
|
|
|
|
|
|
#include "clz.h"
|
|
|
|
#include "LayerBase.h"
|
|
|
|
#include "SurfaceFlinger.h"
|
|
|
|
#include "DisplayHardware/DisplayHardware.h"
|
2010-05-11 03:06:11 +00:00
|
|
|
#include "TextureManager.h"
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace android {
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
|
|
|
: dpy(display), contentDirty(false),
|
|
|
|
mFlinger(flinger),
|
|
|
|
mTransformed(false),
|
2009-09-24 01:34:53 +00:00
|
|
|
mUseLinearFiltering(false),
|
2009-03-04 03:31:44 +00:00
|
|
|
mOrientation(0),
|
2010-02-20 01:51:58 +00:00
|
|
|
mLeft(0), mTop(0),
|
2009-03-04 03:31:44 +00:00
|
|
|
mTransactionFlags(0),
|
2010-04-21 22:24:11 +00:00
|
|
|
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
|
2009-03-04 03:31:44 +00:00
|
|
|
mInvalidate(0)
|
|
|
|
{
|
|
|
|
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
|
|
|
mFlags = hw.getFlags();
|
|
|
|
}
|
|
|
|
|
|
|
|
LayerBase::~LayerBase()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-03-10 03:17:47 +00:00
|
|
|
void LayerBase::setName(const String8& name) {
|
|
|
|
mName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
String8 LayerBase::getName() const {
|
|
|
|
return mName;
|
|
|
|
}
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
const GraphicPlane& LayerBase::graphicPlane(int dpy) const
|
|
|
|
{
|
|
|
|
return mFlinger->graphicPlane(dpy);
|
|
|
|
}
|
|
|
|
|
|
|
|
GraphicPlane& LayerBase::graphicPlane(int dpy)
|
|
|
|
{
|
|
|
|
return mFlinger->graphicPlane(dpy);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
|
|
|
|
{
|
|
|
|
uint32_t layerFlags = 0;
|
|
|
|
if (flags & ISurfaceComposer::eHidden)
|
|
|
|
layerFlags = ISurfaceComposer::eLayerHidden;
|
|
|
|
|
|
|
|
if (flags & ISurfaceComposer::eNonPremultiplied)
|
|
|
|
mPremultipliedAlpha = false;
|
|
|
|
|
2009-09-30 05:39:22 +00:00
|
|
|
mCurrentState.z = 0;
|
|
|
|
mCurrentState.w = w;
|
|
|
|
mCurrentState.h = h;
|
|
|
|
mCurrentState.requested_w = w;
|
|
|
|
mCurrentState.requested_h = h;
|
|
|
|
mCurrentState.alpha = 0xFF;
|
|
|
|
mCurrentState.flags = layerFlags;
|
|
|
|
mCurrentState.sequence = 0;
|
2009-03-04 03:31:44 +00:00
|
|
|
mCurrentState.transform.set(0, 0);
|
|
|
|
|
|
|
|
// drawing state & current state are identical
|
|
|
|
mDrawingState = mCurrentState;
|
|
|
|
}
|
|
|
|
|
2009-09-30 05:32:36 +00:00
|
|
|
void LayerBase::commitTransaction() {
|
2009-03-04 03:31:44 +00:00
|
|
|
mDrawingState = mCurrentState;
|
|
|
|
}
|
|
|
|
void LayerBase::forceVisibilityTransaction() {
|
|
|
|
// this can be called without SurfaceFlinger.mStateLock, but if we
|
|
|
|
// can atomically increment the sequence number, it doesn't matter.
|
|
|
|
android_atomic_inc(&mCurrentState.sequence);
|
|
|
|
requestTransaction();
|
|
|
|
}
|
|
|
|
bool LayerBase::requestTransaction() {
|
|
|
|
int32_t old = setTransactionFlags(eTransactionNeeded);
|
|
|
|
return ((old & eTransactionNeeded) == 0);
|
|
|
|
}
|
|
|
|
uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
|
|
|
|
return android_atomic_and(~flags, &mTransactionFlags) & flags;
|
|
|
|
}
|
|
|
|
uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
|
|
|
|
return android_atomic_or(flags, &mTransactionFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LayerBase::setPosition(int32_t x, int32_t y) {
|
|
|
|
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
|
|
|
|
return false;
|
|
|
|
mCurrentState.sequence++;
|
|
|
|
mCurrentState.transform.set(x, y);
|
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool LayerBase::setLayer(uint32_t z) {
|
|
|
|
if (mCurrentState.z == z)
|
|
|
|
return false;
|
|
|
|
mCurrentState.sequence++;
|
|
|
|
mCurrentState.z = z;
|
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool LayerBase::setSize(uint32_t w, uint32_t h) {
|
2009-09-30 05:39:22 +00:00
|
|
|
if (mCurrentState.requested_w == w && mCurrentState.requested_h == h)
|
2009-03-04 03:31:44 +00:00
|
|
|
return false;
|
2009-09-30 05:39:22 +00:00
|
|
|
mCurrentState.requested_w = w;
|
|
|
|
mCurrentState.requested_h = h;
|
2009-03-04 03:31:44 +00:00
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool LayerBase::setAlpha(uint8_t alpha) {
|
|
|
|
if (mCurrentState.alpha == alpha)
|
|
|
|
return false;
|
|
|
|
mCurrentState.sequence++;
|
|
|
|
mCurrentState.alpha = alpha;
|
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
|
|
|
|
// TODO: check the matrix has changed
|
|
|
|
mCurrentState.sequence++;
|
|
|
|
mCurrentState.transform.set(
|
|
|
|
matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
|
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool LayerBase::setTransparentRegionHint(const Region& transparent) {
|
|
|
|
// TODO: check the region has changed
|
|
|
|
mCurrentState.sequence++;
|
|
|
|
mCurrentState.transparentRegion = transparent;
|
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
|
|
|
|
const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
|
|
|
|
if (mCurrentState.flags == newFlags)
|
|
|
|
return false;
|
|
|
|
mCurrentState.sequence++;
|
|
|
|
mCurrentState.flags = newFlags;
|
|
|
|
requestTransaction();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect LayerBase::visibleBounds() const
|
|
|
|
{
|
|
|
|
return mTransformedBounds;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::setVisibleRegion(const Region& visibleRegion) {
|
|
|
|
// always called from main thread
|
|
|
|
visibleRegionScreen = visibleRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::setCoveredRegion(const Region& coveredRegion) {
|
|
|
|
// always called from main thread
|
|
|
|
coveredRegionScreen = coveredRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t LayerBase::doTransaction(uint32_t flags)
|
|
|
|
{
|
|
|
|
const Layer::State& front(drawingState());
|
|
|
|
const Layer::State& temp(currentState());
|
|
|
|
|
2009-09-30 05:39:22 +00:00
|
|
|
if ((front.requested_w != temp.requested_w) ||
|
|
|
|
(front.requested_h != temp.requested_h)) {
|
|
|
|
// resize the layer, set the physical size to the requested size
|
|
|
|
Layer::State& editTemp(currentState());
|
|
|
|
editTemp.w = temp.requested_w;
|
|
|
|
editTemp.h = temp.requested_h;
|
|
|
|
}
|
2009-09-30 19:48:47 +00:00
|
|
|
|
|
|
|
if ((front.w != temp.w) || (front.h != temp.h)) {
|
|
|
|
// invalidate and recompute the visible regions if needed
|
|
|
|
flags |= Layer::eVisibleRegion;
|
|
|
|
}
|
2009-09-30 05:39:22 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
if (temp.sequence != front.sequence) {
|
|
|
|
// invalidate and recompute the visible regions if needed
|
|
|
|
flags |= eVisibleRegion;
|
|
|
|
this->contentDirty = true;
|
2009-09-24 01:34:53 +00:00
|
|
|
|
|
|
|
const bool linearFiltering = mUseLinearFiltering;
|
|
|
|
mUseLinearFiltering = false;
|
|
|
|
if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
|
|
|
|
// we may use linear filtering, if the matrix scales us
|
|
|
|
const uint8_t type = temp.transform.getType();
|
|
|
|
if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
|
|
|
|
mUseLinearFiltering = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
// Commit the transaction
|
2009-09-30 05:32:36 +00:00
|
|
|
commitTransaction();
|
2009-03-04 03:31:44 +00:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::validateVisibility(const Transform& planeTransform)
|
|
|
|
{
|
|
|
|
const Layer::State& s(drawingState());
|
|
|
|
const Transform tr(planeTransform * s.transform);
|
|
|
|
const bool transformed = tr.transformed();
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
uint32_t w = s.w;
|
|
|
|
uint32_t h = s.h;
|
2009-03-04 03:31:44 +00:00
|
|
|
tr.transform(mVertices[0], 0, 0);
|
|
|
|
tr.transform(mVertices[1], 0, h);
|
|
|
|
tr.transform(mVertices[2], w, h);
|
|
|
|
tr.transform(mVertices[3], w, 0);
|
|
|
|
if (UNLIKELY(transformed)) {
|
|
|
|
// NOTE: here we could also punt if we have too many rectangles
|
|
|
|
// in the transparent region
|
|
|
|
if (tr.preserveRects()) {
|
|
|
|
// transform the transparent region
|
|
|
|
transparentRegionScreen = tr.transform(s.transparentRegion);
|
|
|
|
} else {
|
|
|
|
// transformation too complex, can't do the transparent region
|
|
|
|
// optimization.
|
|
|
|
transparentRegionScreen.clear();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
transparentRegionScreen = s.transparentRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
// cache a few things...
|
|
|
|
mOrientation = tr.getOrientation();
|
|
|
|
mTransformedBounds = tr.makeBounds(w, h);
|
|
|
|
mTransformed = transformed;
|
|
|
|
mLeft = tr.tx();
|
|
|
|
mTop = tr.ty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::unlockPageFlip(
|
|
|
|
const Transform& planeTransform, Region& outDirtyRegion)
|
|
|
|
{
|
|
|
|
if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
|
|
|
|
outDirtyRegion.orSelf(visibleRegionScreen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::finishPageFlip()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::invalidate()
|
|
|
|
{
|
|
|
|
if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
|
|
|
|
mFlinger->signalEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::drawRegion(const Region& reg) const
|
|
|
|
{
|
2009-05-11 07:03:41 +00:00
|
|
|
Region::const_iterator it = reg.begin();
|
|
|
|
Region::const_iterator const end = reg.end();
|
|
|
|
if (it != end) {
|
2009-03-04 03:31:44 +00:00
|
|
|
Rect r;
|
|
|
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
|
|
|
const int32_t fbWidth = hw.getWidth();
|
|
|
|
const int32_t fbHeight = hw.getHeight();
|
|
|
|
const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 },
|
|
|
|
{ fbWidth, fbHeight }, { 0, fbHeight } };
|
|
|
|
glVertexPointer(2, GL_SHORT, 0, vertices);
|
2009-05-11 07:03:41 +00:00
|
|
|
while (it != end) {
|
|
|
|
const Rect& r = *it++;
|
2009-03-04 03:31:44 +00:00
|
|
|
const GLint sy = fbHeight - (r.top + r.height());
|
|
|
|
glScissor(r.left, sy, r.width(), r.height());
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::draw(const Region& inClip) const
|
|
|
|
{
|
|
|
|
// invalidate the region we'll update
|
|
|
|
Region clip(inClip); // copy-on-write, so no-op most of the time
|
|
|
|
|
|
|
|
// Remove the transparent area from the clipping region
|
|
|
|
const State& s = drawingState();
|
|
|
|
if (LIKELY(!s.transparentRegion.isEmpty())) {
|
|
|
|
clip.subtract(transparentRegionScreen);
|
|
|
|
if (clip.isEmpty()) {
|
|
|
|
// usually this won't happen because this should be taken care of
|
|
|
|
// by SurfaceFlinger::computeVisibleRegions()
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// reset GL state
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
|
|
|
|
onDraw(clip);
|
|
|
|
|
|
|
|
/*
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_DITHER);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glColor4x(0, 0x8000, 0, 0x10000);
|
|
|
|
drawRegion(transparentRegionScreen);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2009-09-02 06:06:45 +00:00
|
|
|
void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
|
|
|
|
GLclampx green, GLclampx blue,
|
|
|
|
GLclampx alpha) const
|
2009-03-04 03:31:44 +00:00
|
|
|
{
|
|
|
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
|
|
|
const uint32_t fbHeight = hw.getHeight();
|
2009-09-02 06:06:45 +00:00
|
|
|
glColor4x(red,green,blue,alpha);
|
2009-03-04 03:31:44 +00:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDisable(GL_DITHER);
|
2009-05-11 07:03:41 +00:00
|
|
|
|
|
|
|
Region::const_iterator it = clip.begin();
|
|
|
|
Region::const_iterator const end = clip.end();
|
2009-09-24 21:57:26 +00:00
|
|
|
glEnable(GL_SCISSOR_TEST);
|
2010-04-20 21:51:04 +00:00
|
|
|
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
2009-09-24 21:57:26 +00:00
|
|
|
while (it != end) {
|
|
|
|
const Rect& r = *it++;
|
|
|
|
const GLint sy = fbHeight - (r.top + r.height());
|
|
|
|
glScissor(r.left, sy, r.width(), r.height());
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
2009-03-04 03:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-02 06:06:45 +00:00
|
|
|
void LayerBase::clearWithOpenGL(const Region& clip) const
|
|
|
|
{
|
|
|
|
clearWithOpenGL(clip,0,0,0,0);
|
|
|
|
}
|
|
|
|
|
2009-06-24 01:08:22 +00:00
|
|
|
void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
|
2009-03-04 03:31:44 +00:00
|
|
|
{
|
|
|
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
|
|
|
const uint32_t fbHeight = hw.getHeight();
|
|
|
|
const State& s(drawingState());
|
2009-05-04 21:17:04 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
// bind our texture
|
2009-06-24 01:08:22 +00:00
|
|
|
validateTexture(texture.name);
|
|
|
|
uint32_t width = texture.width;
|
|
|
|
uint32_t height = texture.height;
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
if (UNLIKELY(s.alpha < 0xFF)) {
|
|
|
|
// We have an alpha-modulation. We need to modulate all
|
|
|
|
// texture components by alpha because we're always using
|
|
|
|
// premultiplied alpha.
|
|
|
|
|
|
|
|
// If the texture doesn't have an alpha channel we can
|
|
|
|
// use REPLACE and switch to non premultiplied alpha
|
|
|
|
// blending (SRCA/ONE_MINUS_SRCA).
|
|
|
|
|
|
|
|
GLenum env, src;
|
|
|
|
if (needsBlending()) {
|
|
|
|
env = GL_MODULATE;
|
|
|
|
src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
|
|
|
} else {
|
|
|
|
env = GL_REPLACE;
|
|
|
|
src = GL_SRC_ALPHA;
|
|
|
|
}
|
2010-04-20 21:51:04 +00:00
|
|
|
const GLfloat alpha = s.alpha * (1.0f/255.0f);
|
|
|
|
glColor4f(alpha, alpha, alpha, alpha);
|
2009-03-04 03:31:44 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
|
|
|
|
} else {
|
|
|
|
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
2010-04-20 21:51:04 +00:00
|
|
|
glColor4f(1, 1, 1, 1);
|
2009-03-04 03:31:44 +00:00
|
|
|
if (needsBlending()) {
|
|
|
|
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
} else {
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-24 21:57:26 +00:00
|
|
|
Region::const_iterator it = clip.begin();
|
|
|
|
Region::const_iterator const end = clip.end();
|
2010-04-20 21:51:04 +00:00
|
|
|
const GLfloat texCoords[4][2] = {
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 0, 1 },
|
|
|
|
{ 1, 1 },
|
|
|
|
{ 1, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
// the texture's source is rotated
|
|
|
|
switch (texture.transform) {
|
|
|
|
case HAL_TRANSFORM_ROT_90:
|
|
|
|
glTranslatef(0, 1, 0);
|
|
|
|
glRotatef(-90, 0, 0, 1);
|
|
|
|
break;
|
|
|
|
case HAL_TRANSFORM_ROT_180:
|
|
|
|
glTranslatef(1, 1, 0);
|
|
|
|
glRotatef(-180, 0, 0, 1);
|
|
|
|
break;
|
|
|
|
case HAL_TRANSFORM_ROT_270:
|
|
|
|
glTranslatef(1, 0, 0);
|
|
|
|
glRotatef(-270, 0, 0, 1);
|
|
|
|
break;
|
|
|
|
}
|
2010-01-23 00:30:39 +00:00
|
|
|
|
2010-04-20 21:51:04 +00:00
|
|
|
if (texture.NPOTAdjust) {
|
|
|
|
glScalef(texture.wScale, texture.hScale, 1.0f);
|
|
|
|
}
|
2009-03-04 03:31:44 +00:00
|
|
|
|
2010-04-20 21:51:04 +00:00
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
|
2009-03-04 03:31:44 +00:00
|
|
|
|
2010-04-20 21:51:04 +00:00
|
|
|
while (it != end) {
|
|
|
|
const Rect& r = *it++;
|
|
|
|
const GLint sy = fbHeight - (r.top + r.height());
|
|
|
|
glScissor(r.left, sy, r.width(), r.height());
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
2009-03-04 03:31:44 +00:00
|
|
|
}
|
2010-04-20 21:51:04 +00:00
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
2009-03-04 03:31:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBase::validateTexture(GLint textureName) const
|
|
|
|
{
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textureName);
|
|
|
|
// TODO: reload the texture if needed
|
|
|
|
// this is currently done in loadTexture() below
|
2009-09-24 01:34:53 +00:00
|
|
|
if (mUseLinearFiltering) {
|
|
|
|
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
} else {
|
|
|
|
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
}
|
2009-09-24 02:16:27 +00:00
|
|
|
|
|
|
|
if (needsDithering()) {
|
|
|
|
glEnable(GL_DITHER);
|
|
|
|
} else {
|
|
|
|
glDisable(GL_DITHER);
|
|
|
|
}
|
2009-03-04 03:31:44 +00:00
|
|
|
}
|
|
|
|
|
2010-04-21 00:55:49 +00:00
|
|
|
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
|
|
|
{
|
|
|
|
const Layer::State& s(drawingState());
|
|
|
|
snprintf(buffer, SIZE,
|
|
|
|
"+ %s %p\n"
|
|
|
|
" "
|
|
|
|
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
|
|
|
|
"needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
|
|
|
|
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
|
|
|
|
getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
|
|
|
|
needsBlending(), needsDithering(), contentDirty,
|
|
|
|
s.alpha, s.flags,
|
|
|
|
s.transform[0][0], s.transform[0][1],
|
|
|
|
s.transform[1][0], s.transform[1][1]);
|
|
|
|
result.append(buffer);
|
|
|
|
}
|
2009-10-27 03:12:37 +00:00
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2009-06-24 03:06:46 +00:00
|
|
|
int32_t LayerBaseClient::sIdentity = 0;
|
|
|
|
|
2009-03-04 03:31:44 +00:00
|
|
|
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
2009-06-20 00:00:27 +00:00
|
|
|
const sp<Client>& client, int32_t i)
|
2010-05-11 03:06:11 +00:00
|
|
|
: LayerBase(flinger, display), client(client), mIndex(i),
|
2010-03-09 03:29:09 +00:00
|
|
|
mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
|
2009-03-04 03:31:44 +00:00
|
|
|
{
|
2009-04-10 21:24:30 +00:00
|
|
|
}
|
2009-03-04 03:31:44 +00:00
|
|
|
|
2009-04-10 21:24:30 +00:00
|
|
|
void LayerBaseClient::onFirstRef()
|
|
|
|
{
|
2009-06-20 00:00:27 +00:00
|
|
|
sp<Client> client(this->client.promote());
|
|
|
|
if (client != 0) {
|
2009-04-10 21:24:30 +00:00
|
|
|
client->bindLayer(this, mIndex);
|
2009-03-04 03:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LayerBaseClient::~LayerBaseClient()
|
|
|
|
{
|
2009-06-20 00:00:27 +00:00
|
|
|
sp<Client> client(this->client.promote());
|
|
|
|
if (client != 0) {
|
2009-03-04 03:31:44 +00:00
|
|
|
client->free(mIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-21 00:55:49 +00:00
|
|
|
ssize_t LayerBaseClient::serverIndex() const
|
2009-06-20 00:00:27 +00:00
|
|
|
{
|
|
|
|
sp<Client> client(this->client.promote());
|
|
|
|
if (client != 0) {
|
2009-03-04 03:31:44 +00:00
|
|
|
return (client->cid<<16)|mIndex;
|
|
|
|
}
|
2010-04-21 00:55:49 +00:00
|
|
|
return ssize_t(0xFFFF0000 | mIndex);
|
2009-03-04 03:31:44 +00:00
|
|
|
}
|
|
|
|
|
2009-04-10 21:24:30 +00:00
|
|
|
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
|
|
|
|
{
|
|
|
|
sp<Surface> s;
|
|
|
|
Mutex::Autolock _l(mLock);
|
|
|
|
s = mClientSurface.promote();
|
|
|
|
if (s == 0) {
|
|
|
|
s = createSurface();
|
|
|
|
mClientSurface = s;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
|
|
|
|
{
|
2009-04-18 02:36:26 +00:00
|
|
|
return new Surface(mFlinger, clientIndex(), mIdentity,
|
2009-04-10 21:24:30 +00:00
|
|
|
const_cast<LayerBaseClient *>(this));
|
|
|
|
}
|
|
|
|
|
2010-04-21 00:55:49 +00:00
|
|
|
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
|
|
|
|
{
|
|
|
|
LayerBase::dump(result, buffer, SIZE);
|
|
|
|
|
|
|
|
sp<Client> client(this->client.promote());
|
|
|
|
snprintf(buffer, SIZE,
|
|
|
|
" name=%s\n"
|
|
|
|
" id=0x%08x, client=0x%08x, identity=%u\n",
|
|
|
|
getName().string(),
|
|
|
|
clientIndex(), client.get() ? client->cid : 0,
|
|
|
|
getIdentity());
|
|
|
|
|
|
|
|
result.append(buffer);
|
|
|
|
}
|
|
|
|
|
2009-04-10 21:24:30 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2009-04-18 02:36:26 +00:00
|
|
|
LayerBaseClient::Surface::Surface(
|
|
|
|
const sp<SurfaceFlinger>& flinger,
|
|
|
|
SurfaceID id, int identity,
|
2009-04-10 21:24:30 +00:00
|
|
|
const sp<LayerBaseClient>& owner)
|
2009-04-18 02:36:26 +00:00
|
|
|
: mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner)
|
|
|
|
{
|
2009-04-10 21:24:30 +00:00
|
|
|
}
|
|
|
|
|
2009-04-18 02:36:26 +00:00
|
|
|
LayerBaseClient::Surface::~Surface()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This is a good place to clean-up all client resources
|
|
|
|
*/
|
|
|
|
|
|
|
|
// destroy client resources
|
|
|
|
sp<LayerBaseClient> layer = getOwner();
|
|
|
|
if (layer != 0) {
|
|
|
|
mFlinger->destroySurface(layer);
|
|
|
|
}
|
2009-04-10 21:24:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
|
|
|
|
sp<LayerBaseClient> owner(mOwner.promote());
|
|
|
|
return owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t LayerBaseClient::Surface::onTransact(
|
2009-06-16 01:24:59 +00:00
|
|
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
2009-04-10 21:24:30 +00:00
|
|
|
{
|
|
|
|
switch (code) {
|
|
|
|
case REGISTER_BUFFERS:
|
|
|
|
case UNREGISTER_BUFFERS:
|
|
|
|
case CREATE_OVERLAY:
|
|
|
|
{
|
2009-06-16 01:24:59 +00:00
|
|
|
if (!mFlinger->mAccessSurfaceFlinger.checkCalling()) {
|
|
|
|
IPCThreadState* ipc = IPCThreadState::self();
|
|
|
|
const int pid = ipc->getCallingPid();
|
|
|
|
const int uid = ipc->getCallingUid();
|
|
|
|
LOGE("Permission Denial: "
|
|
|
|
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
|
|
|
|
return PERMISSION_DENIED;
|
2009-04-10 21:24:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return BnSurface::onTransact(code, data, reply, flags);
|
|
|
|
}
|
|
|
|
|
2010-05-22 00:24:35 +00:00
|
|
|
sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
|
|
|
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
|
2009-04-10 21:24:30 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-05-07 22:58:44 +00:00
|
|
|
status_t LayerBaseClient::Surface::setBufferCount(int bufferCount)
|
|
|
|
{
|
|
|
|
return INVALID_OPERATION;
|
|
|
|
}
|
|
|
|
|
2009-04-10 21:24:30 +00:00
|
|
|
status_t LayerBaseClient::Surface::registerBuffers(
|
|
|
|
const ISurface::BufferHeap& buffers)
|
|
|
|
{
|
|
|
|
return INVALID_OPERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBaseClient::Surface::postBuffer(ssize_t offset)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayerBaseClient::Surface::unregisterBuffers()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
sp<OverlayRef> LayerBaseClient::Surface::createOverlay(
|
2010-01-22 01:31:06 +00:00
|
|
|
uint32_t w, uint32_t h, int32_t format, int32_t orientation)
|
2009-04-10 21:24:30 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
};
|
2009-03-04 03:31:44 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
}; // namespace android
|