Example #1
0
  /**
   * Copies the content of this view's surface texture into the specified bitmap. If the surface
   * texture is not available, the copy is not executed. The content of the surface texture will be
   * scaled to fit exactly inside the specified bitmap.
   *
   * <p><strong>Do not</strong> invoke this method from a drawing method ({@link
   * #onDraw(android.graphics.Canvas)} for instance).
   *
   * <p>If an error occurs, the bitmap is left unchanged.
   *
   * @param bitmap The bitmap to copy the content of the surface texture into, cannot be null, all
   *     configurations are supported
   * @return The bitmap specified as a parameter
   * @see #isAvailable()
   * @see #getBitmap(int, int)
   * @see #getBitmap()
   * @throws IllegalStateException if the hardware rendering context cannot be acquired to capture
   *     the bitmap
   */
  public Bitmap getBitmap(Bitmap bitmap) {
    if (bitmap != null && isAvailable()) {
      AttachInfo info = mAttachInfo;
      if (info != null && info.mHardwareRenderer != null && info.mHardwareRenderer.isEnabled()) {
        if (!info.mHardwareRenderer.validate()) {
          throw new IllegalStateException("Could not acquire hardware rendering context");
        }
      }

      applyUpdate();
      applyTransformMatrix();

      // This case can happen if the app invokes setSurfaceTexture() before
      // we are able to create the hardware layer. We can safely initialize
      // the layer here thanks to the validate() call at the beginning of
      // this method
      if (mLayer == null && mUpdateSurface) {
        getHardwareLayer();
      }

      if (mLayer != null) {
        mLayer.copyInto(bitmap);
      }
    }
    return bitmap;
  }
Example #2
0
  private void destroySurface() {
    if (mLayer != null) {
      mSurface.detachFromGLContext();
      // SurfaceTexture owns the texture name and detachFromGLContext
      // should have deleted it
      mLayer.clearStorage();

      boolean shouldRelease = true;
      if (mListener != null) {
        shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
      }

      synchronized (mNativeWindowLock) {
        nDestroyNativeWindow();
      }

      mLayer.destroy();
      if (shouldRelease) mSurface.release();
      mSurface = null;
      mLayer = null;

      mHadSurface = true;
    }
  }
Example #3
0
  private void applyUpdate() {
    if (mLayer == null) {
      return;
    }

    synchronized (mLock) {
      if (mUpdateLayer) {
        mUpdateLayer = false;
      } else {
        return;
      }
    }

    mLayer.update(getWidth(), getHeight(), mOpaque);

    if (mListener != null) {
      mListener.onSurfaceTextureUpdated(mSurface);
    }
  }
Example #4
0
 private void applyTransformMatrix() {
   if (mMatrixChanged && mLayer != null) {
     mLayer.setTransform(mMatrix);
     mMatrixChanged = false;
   }
 }
Example #5
0
  @Override
  HardwareLayer getHardwareLayer() {
    // NOTE: Maintain these two lines very carefully (see View.java)
    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
    mPrivateFlags &= ~PFLAG_DIRTY_MASK;

    if (mLayer == null) {
      if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
        return null;
      }

      mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
      if (!mUpdateSurface) {
        // Create a new SurfaceTexture for the layer.
        mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
      }
      mSurface.setDefaultBufferSize(getWidth(), getHeight());
      nCreateNativeWindow(mSurface);

      mUpdateListener =
          new SurfaceTexture.OnFrameAvailableListener() {
            @Override
            public void onFrameAvailable(SurfaceTexture surfaceTexture) {
              // Per SurfaceTexture's documentation, the callback may be invoked
              // from an arbitrary thread
              updateLayer();

              if (Looper.myLooper() == Looper.getMainLooper()) {
                invalidate();
              } else {
                postInvalidate();
              }
            }
          };
      mSurface.setOnFrameAvailableListener(mUpdateListener);

      if (mListener != null && !mUpdateSurface) {
        mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
      }
      mLayer.setLayerPaint(mLayerPaint);
    }

    if (mUpdateSurface) {
      // Someone has requested that we use a specific SurfaceTexture, so
      // tell mLayer about it and set the SurfaceTexture to use the
      // current view size.
      mUpdateSurface = false;

      // Since we are updating the layer, force an update to ensure its
      // parameters are correct (width, height, transform, etc.)
      updateLayer();
      mMatrixChanged = true;

      mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
      mSurface.setDefaultBufferSize(getWidth(), getHeight());
    }

    applyUpdate();
    applyTransformMatrix();

    return mLayer;
  }