Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.content.res.CompatibilityInfo.Translator;
     20 import android.graphics.*;
     21 import android.os.Parcelable;
     22 import android.os.Parcel;
     23 import android.util.DisplayMetrics;
     24 import android.util.Log;
     25 
     26 /**
     27  * Handle on to a raw buffer that is being managed by the screen compositor.
     28  */
     29 public class Surface implements Parcelable {
     30     private static final String LOG_TAG = "Surface";
     31     private static final boolean DEBUG_RELEASE = false;
     32 
     33     /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
     34 
     35     /** Surface is created hidden */
     36     public static final int HIDDEN              = 0x00000004;
     37 
     38     /** The surface is to be used by hardware accelerators or DMA engines
     39      * @deprecated this is ignored, this value is set automatically when needed.
     40      */
     41     @Deprecated
     42     public static final int HARDWARE            = 0x00000010;
     43 
     44     /** Implies "HARDWARE", the surface is to be used by the GPU
     45      * additionally the backbuffer is never preserved for these
     46      * surfaces.
     47      * @deprecated this is ignored, this value is set automatically when needed.
     48      */
     49     @Deprecated
     50     public static final int GPU                 = 0x00000028;
     51 
     52     /** The surface contains secure content, special measures will
     53      * be taken to disallow the surface's content to be copied from
     54      * another process. In particular, screenshots and VNC servers will
     55      * be disabled, but other measures can take place, for instance the
     56      * surface might not be hardware accelerated. */
     57     public static final int SECURE              = 0x00000080;
     58 
     59     /** Creates a surface where color components are interpreted as
     60      *  "non pre-multiplied" by their alpha channel. Of course this flag is
     61      *  meaningless for surfaces without an alpha channel. By default
     62      *  surfaces are pre-multiplied, which means that each color component is
     63      *  already multiplied by its alpha value. In this case the blending
     64      *  equation used is:
     65      *
     66      *    DEST = SRC + DEST * (1-SRC_ALPHA)
     67      *
     68      *  By contrast, non pre-multiplied surfaces use the following equation:
     69      *
     70      *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
     71      *
     72      *  pre-multiplied surfaces must always be used if transparent pixels are
     73      *  composited on top of each-other into the surface. A pre-multiplied
     74      *  surface can never lower the value of the alpha component of a given
     75      *  pixel.
     76      *
     77      *  In some rare situations, a non pre-multiplied surface is preferable.
     78      *
     79      */
     80     public static final int NON_PREMULTIPLIED   = 0x00000100;
     81 
     82     /**
     83      * Creates a surface without a rendering buffer. Instead, the content
     84      * of the surface must be pushed by an external entity. This is type
     85      * of surface can be used for efficient camera preview or movie
     86      * play back.
     87      */
     88     public static final int PUSH_BUFFERS        = 0x00000200;
     89 
     90     /** Creates a normal surface. This is the default */
     91     public static final int FX_SURFACE_NORMAL   = 0x00000000;
     92 
     93     /** Creates a Blur surface. Everything behind this surface is blurred
     94      * by some amount. The quality and refresh speed of the blur effect
     95      * is not settable or guaranteed.
     96      * It is an error to lock a Blur surface, since it doesn't have
     97      * a backing store.
     98      */
     99     public static final int FX_SURFACE_BLUR     = 0x00010000;
    100 
    101     /** Creates a Dim surface. Everything behind this surface is dimmed
    102      * by the amount specified in setAlpha().
    103      * It is an error to lock a Dim surface, since it doesn't have
    104      * a backing store.
    105      */
    106     public static final int FX_SURFACE_DIM     = 0x00020000;
    107 
    108     /** Mask used for FX values above */
    109     public static final int FX_SURFACE_MASK     = 0x000F0000;
    110 
    111     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
    112 
    113     /** Hide the surface. Equivalent to calling hide() */
    114     public static final int SURFACE_HIDDEN    = 0x01;
    115 
    116     /** Freeze the surface. Equivalent to calling freeze() */
    117     public static final int SURFACE_FROZEN     = 0x02;
    118 
    119     /**
    120      * @deprecated use {@link #SURFACE_FROZEN} instead.
    121      */
    122     @Deprecated
    123     public static final int SURACE_FROZEN     = 0x02;
    124 
    125     /** Enable dithering when compositing this surface */
    126     public static final int SURFACE_DITHER    = 0x04;
    127 
    128     public static final int SURFACE_BLUR_FREEZE= 0x10;
    129 
    130     /* orientations for setOrientation() */
    131     public static final int ROTATION_0       = 0;
    132     public static final int ROTATION_90      = 1;
    133     public static final int ROTATION_180     = 2;
    134     public static final int ROTATION_270     = 3;
    135 
    136     /**
    137      * Disable the orientation animation
    138      * {@hide}
    139      */
    140     public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001;
    141 
    142     @SuppressWarnings("unused")
    143     private int mSurfaceControl;
    144     @SuppressWarnings("unused")
    145     private int mSaveCount;
    146     @SuppressWarnings("unused")
    147     private Canvas mCanvas;
    148     @SuppressWarnings("unused")
    149     private int mNativeSurface;
    150     private String mName;
    151 
    152     // The display metrics used to provide the pseudo canvas size for applications
    153     // running in compatibility mode. This is set to null for non compatibility mode.
    154     private DisplayMetrics mCompatibleDisplayMetrics;
    155 
    156     // A matrix to scale the matrix set by application. This is set to null for
    157     // non compatibility mode.
    158     private Matrix mCompatibleMatrix;
    159 
    160     @SuppressWarnings("unused")
    161     private Exception mCreationStack;
    162 
    163     /**
    164      * Exception thrown when a surface couldn't be created or resized
    165      */
    166     public static class OutOfResourcesException extends Exception {
    167         public OutOfResourcesException() {
    168         }
    169         public OutOfResourcesException(String name) {
    170             super(name);
    171         }
    172     }
    173 
    174     /*
    175      * We use a class initializer to allow the native code to cache some
    176      * field offsets.
    177      */
    178     native private static void nativeClassInit();
    179     static { nativeClassInit(); }
    180 
    181 
    182     /**
    183      * create a surface
    184      * {@hide}
    185      */
    186     public Surface(SurfaceSession s,
    187             int pid, int display, int w, int h, int format, int flags)
    188         throws OutOfResourcesException {
    189         if (DEBUG_RELEASE) {
    190             mCreationStack = new Exception();
    191         }
    192         mCanvas = new CompatibleCanvas();
    193         init(s,pid,null,display,w,h,format,flags);
    194     }
    195 
    196     /**
    197      * create a surface with a name
    198      * {@hide}
    199      */
    200     public Surface(SurfaceSession s,
    201             int pid, String name, int display, int w, int h, int format, int flags)
    202         throws OutOfResourcesException {
    203         if (DEBUG_RELEASE) {
    204             mCreationStack = new Exception();
    205         }
    206         mCanvas = new CompatibleCanvas();
    207         init(s,pid,name,display,w,h,format,flags);
    208         mName = name;
    209     }
    210 
    211     /**
    212      * Create an empty surface, which will later be filled in by
    213      * readFromParcel().
    214      * {@hide}
    215      */
    216     public Surface() {
    217         if (DEBUG_RELEASE) {
    218             mCreationStack = new Exception();
    219         }
    220         mCanvas = new CompatibleCanvas();
    221     }
    222 
    223     /**
    224      * A Canvas class that can handle the compatibility mode. This does two things differently.
    225      * <ul>
    226      *  <li> Returns the width and height of the target metrics, rather than native.
    227      *  For example, the canvas returns 320x480 even if an app is running in WVGA high density.
    228      *  <li> Scales the matrix in setMatrix by the application scale, except if the matrix looks
    229      *  like obtained from getMatrix. This is a hack to handle the case that an application
    230      *  uses getMatrix to keep the original matrix, set matrix of its own, then set the original
    231      *  matrix back. There is no perfect solution that works for all cases, and there are a lot of
    232      *  cases that this model dose not work, but we hope this works for many apps.
    233      * </ul>
    234      */
    235     private class CompatibleCanvas extends Canvas {
    236         // A temp matrix to remember what an application obtained via {@link getMatrix}
    237         private Matrix mOrigMatrix = null;
    238 
    239         @Override
    240         public int getWidth() {
    241             return mCompatibleDisplayMetrics == null ?
    242                     super.getWidth() : mCompatibleDisplayMetrics.widthPixels;
    243         }
    244 
    245         @Override
    246         public int getHeight() {
    247             return mCompatibleDisplayMetrics == null ?
    248                     super.getHeight() : mCompatibleDisplayMetrics.heightPixels;
    249         }
    250 
    251         @Override
    252         public void setMatrix(Matrix matrix) {
    253             if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
    254                 // don't scale the matrix if it's not compatibility mode, or
    255                 // the matrix was obtained from getMatrix.
    256                 super.setMatrix(matrix);
    257             } else {
    258                 Matrix m = new Matrix(mCompatibleMatrix);
    259                 m.preConcat(matrix);
    260                 super.setMatrix(m);
    261             }
    262         }
    263 
    264         @Override
    265         public void getMatrix(Matrix m) {
    266             super.getMatrix(m);
    267             if (mOrigMatrix == null) {
    268                 mOrigMatrix = new Matrix();
    269             }
    270             mOrigMatrix.set(m);
    271         }
    272     };
    273 
    274     /**
    275      * Sets the display metrics used to provide canva's width/height in compatibility mode.
    276      */
    277     void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) {
    278         mCompatibleDisplayMetrics = metrics;
    279         if (translator != null) {
    280             float appScale = translator.applicationScale;
    281             mCompatibleMatrix = new Matrix();
    282             mCompatibleMatrix.setScale(appScale, appScale);
    283         }
    284     }
    285 
    286     /**
    287      * Copy another surface to this one.  This surface now holds a reference
    288      * to the same data as the original surface, and is -not- the owner.
    289      * {@hide}
    290      */
    291     public native   void copyFrom(Surface o);
    292 
    293     /**
    294      * Does this object hold a valid surface?  Returns true if it holds
    295      * a physical surface, so lockCanvas() will succeed.  Otherwise
    296      * returns false.
    297      */
    298     public native   boolean isValid();
    299 
    300     /** Free all server-side state associated with this surface and
    301      * release this object's reference. {@hide} */
    302     public native void destroy();
    303 
    304     /** Release the local reference to the server-side surface. @hide */
    305     public native void release();
    306 
    307     /** draw into a surface */
    308     public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException
    309     {
    310         /* the dirty rectangle may be expanded to the surface's size, if
    311          * for instance it has been resized or if the bits were lost, since
    312          * the last call.
    313          */
    314         return lockCanvasNative(dirty);
    315     }
    316 
    317     private native Canvas lockCanvasNative(Rect dirty);
    318 
    319     /** unlock the surface and asks a page flip */
    320     public native   void unlockCanvasAndPost(Canvas canvas);
    321 
    322     /**
    323      * unlock the surface. the screen won't be updated until
    324      * post() or postAll() is called
    325      */
    326     public native   void unlockCanvas(Canvas canvas);
    327 
    328     /** start/end a transaction {@hide} */
    329     public static native   void openTransaction();
    330     /** {@hide} */
    331     public static native   void closeTransaction();
    332 
    333     /**
    334      * Freezes the specified display, No updating of the screen will occur
    335      * until unfreezeDisplay() is called. Everything else works as usual though,
    336      * in particular transactions.
    337      * @param display
    338      * {@hide}
    339      */
    340     public static native   void freezeDisplay(int display);
    341 
    342     /**
    343      * resume updating the specified display.
    344      * @param display
    345      * {@hide}
    346      */
    347     public static native   void unfreezeDisplay(int display);
    348 
    349     /**
    350      * set the orientation of the given display.
    351      * @param display
    352      * @param orientation
    353      * @param flags
    354      * {@hide}
    355      */
    356     public static native   void setOrientation(int display, int orientation, int flags);
    357 
    358     /**
    359      * set the orientation of the given display.
    360      * @param display
    361      * @param orientation
    362      */
    363     public static void setOrientation(int display, int orientation) {
    364         setOrientation(display, orientation, 0);
    365     }
    366 
    367     /**
    368      * set surface parameters.
    369      * needs to be inside open/closeTransaction block
    370      */
    371     public native   void setLayer(int zorder);
    372     public native   void setPosition(int x, int y);
    373     public native   void setSize(int w, int h);
    374 
    375     public native   void hide();
    376     public native   void show();
    377     public native   void setTransparentRegionHint(Region region);
    378     public native   void setAlpha(float alpha);
    379     public native   void setMatrix(float dsdx, float dtdx,
    380                                    float dsdy, float dtdy);
    381 
    382     public native   void freeze();
    383     public native   void unfreeze();
    384 
    385     public native   void setFreezeTint(int tint);
    386 
    387     public native   void setFlags(int flags, int mask);
    388 
    389     @Override
    390     public String toString() {
    391         return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
    392     }
    393 
    394     private Surface(Parcel source) throws OutOfResourcesException {
    395         init(source);
    396     }
    397 
    398     public int describeContents() {
    399         return 0;
    400     }
    401 
    402     public native   void readFromParcel(Parcel source);
    403     public native   void writeToParcel(Parcel dest, int flags);
    404 
    405     public static final Parcelable.Creator<Surface> CREATOR
    406             = new Parcelable.Creator<Surface>()
    407     {
    408         public Surface createFromParcel(Parcel source) {
    409             try {
    410                 return new Surface(source);
    411             } catch (Exception e) {
    412                 Log.e(LOG_TAG, "Exception creating surface from parcel", e);
    413             }
    414             return null;
    415         }
    416 
    417         public Surface[] newArray(int size) {
    418             return new Surface[size];
    419         }
    420     };
    421 
    422     /* no user serviceable parts here ... */
    423     @Override
    424     protected void finalize() throws Throwable {
    425         if (mNativeSurface != 0 || mSurfaceControl != 0) {
    426             if (DEBUG_RELEASE) {
    427                 Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() ("
    428                         + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack);
    429             } else {
    430                 Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() ("
    431                         + mNativeSurface + ", " + mSurfaceControl + ")");
    432             }
    433         }
    434         release();
    435     }
    436 
    437     private native void init(SurfaceSession s,
    438             int pid, String name, int display, int w, int h, int format, int flags)
    439             throws OutOfResourcesException;
    440 
    441     private native void init(Parcel source);
    442 
    443     private native int getIdentity();
    444 }
    445