Merge "Allocate layers from the layers pool. Bug #3413433" into honeycomb

This commit is contained in:
Romain Guy
2011-02-02 21:05:35 -08:00
committed by Android (Google) Code Review
9 changed files with 306 additions and 81 deletions

View File

@@ -66,10 +66,11 @@ class GLES20Layer extends HardwareLayer {
@Override
void resize(int width, int height) {
if (!isValid() || width <= 0 || height <= 0) return;
if (width > mLayerWidth || height > mLayerHeight) {
mWidth = width;
mHeight = height;
mWidth = width;
mHeight = height;
if (width != mLayerWidth || height != mLayerHeight) {
int[] layerInfo = new int[2];
GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo);

View File

@@ -20,6 +20,7 @@
#include "Caches.h"
#include "Properties.h"
#include "LayerRenderer.h"
namespace android {
@@ -116,12 +117,7 @@ void Caches::clearGarbage() {
size_t count = mLayerGarbage.size();
for (size_t i = 0; i < count; i++) {
Layer* layer = mLayerGarbage.itemAt(i);
if (layer) {
if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
if (layer->texture) glDeleteTextures(1, &layer->texture);
delete layer;
}
LayerRenderer::destroyLayer(layer);
}
mLayerGarbage.clear();
}

View File

@@ -128,6 +128,31 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) {
return layer;
}
bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) {
// TODO: We should be smarter and see if we have a texture of the appropriate
// size already in the cache, and reuse it instead of creating a new one
LayerEntry entry(width, height);
if (entry.mWidth <= layer->width && entry.mHeight <= layer->height) {
return true;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, layer->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry.mWidth, entry.mHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (glGetError() != GL_NO_ERROR) {
return false;
}
layer->width = entry.mWidth;
layer->height = entry.mHeight;
return true;
}
bool LayerCache::put(Layer* layer) {
const uint32_t size = layer->width * layer->height * 4;
// Don't even try to cache a layer that's bigger than the cache

View File

@@ -76,6 +76,17 @@ public:
* Clears the cache. This causes all layers to be deleted.
*/
void clear();
/**
* Resize the specified layer if needed.
*
* @param layer The layer to resize
* @param width The new width of the layer
* @param height The new height of the layer
*
* @return True if the layer was resized or nothing happened, false if
* a failure occurred during the resizing operation
*/
bool resize(Layer* layer, const uint32_t width, const uint32_t height);
/**
* Sets the maximum size of the cache in bytes.

View File

@@ -18,6 +18,7 @@
#include <ui/Rect.h>
#include "LayerCache.h"
#include "LayerRenderer.h"
#include "Properties.h"
#include "Rect.h"
@@ -34,21 +35,24 @@ void LayerRenderer::prepareDirty(float left, float top, float right, float botto
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
const float width = mLayer->layer.getWidth();
const float height = mLayer->layer.getHeight();
#if RENDER_LAYERS_AS_REGIONS
Rect dirty(left, top, right, bottom);
if (dirty.isEmpty() || (dirty.left <= 0 && dirty.top <= 0 &&
dirty.right >= mLayer->width && dirty.bottom >= mLayer->height)) {
dirty.right >= width && dirty.bottom >= height)) {
mLayer->region.clear();
dirty.set(0.0f, 0.0f, mLayer->width, mLayer->height);
dirty.set(0.0f, 0.0f, width, height);
} else {
dirty.intersect(0.0f, 0.0f, mLayer->width, mLayer->height);
dirty.intersect(0.0f, 0.0f, width, height);
android::Rect r(dirty.left, dirty.top, dirty.right, dirty.bottom);
mLayer->region.subtractSelf(r);
}
OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
#else
OpenGLRenderer::prepareDirty(0.0f, 0.0f, mLayer->width, mLayer->height, opaque);
OpenGLRenderer::prepareDirty(0.0f, 0.0f, width, height, opaque);
#endif
}
@@ -162,64 +166,56 @@ void LayerRenderer::generateMesh() {
Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
Layer* layer = new Layer(width, height);
GLuint fbo = Caches::getInstance().fboCache.get();
if (!fbo) {
LOGW("Could not obtain an FBO");
return NULL;
}
glActiveTexture(GL_TEXTURE0);
Layer* layer = Caches::getInstance().layerCache.get(width, height);
if (!layer) {
LOGW("Could not obtain a layer");
return NULL;
}
layer->fbo = fbo;
layer->layer.set(0.0f, 0.0f, width, height);
layer->texCoords.set(0.0f, height / float(layer->height),
width / float(layer->width), 0.0f);
layer->alpha = 255;
layer->mode = SkXfermode::kSrcOver_Mode;
layer->blend = !isOpaque;
layer->colorFilter = NULL;
layer->region.clear();
GLuint previousFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
glGenFramebuffers(1, &layer->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
if (glGetError() != GL_NO_ERROR) {
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
glDeleteBuffers(1, &layer->fbo);
return 0;
}
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &layer->texture);
glBindTexture(GL_TEXTURE_2D, layer->texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
// Initialize the texture if needed
if (layer->empty) {
layer->empty = false;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (glGetError() != GL_NO_ERROR) {
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
glDeleteBuffers(1, &layer->fbo);
glDeleteTextures(1, &layer->texture);
delete layer;
return 0;
if (glGetError() != GL_NO_ERROR) {
LOGD("Could not allocate texture");
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
glDeleteTextures(1, &layer->texture);
Caches::getInstance().fboCache.put(fbo);
delete layer;
return NULL;
}
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->texture, 0);
if (glGetError() != GL_NO_ERROR) {
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
glDeleteBuffers(1, &layer->fbo);
glDeleteTextures(1, &layer->texture);
delete layer;
return 0;
}
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
layer->layer.set(0.0f, 0.0f, width, height);
layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
layer->alpha = 255;
layer->mode = SkXfermode::kSrcOver_Mode;
layer->blend = !isOpaque;
layer->empty = false;
layer->colorFilter = NULL;
return layer;
}
@@ -227,27 +223,17 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
if (layer) {
LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, layer->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (glGetError() != GL_NO_ERROR) {
glDeleteBuffers(1, &layer->fbo);
glDeleteTextures(1, &layer->texture);
layer->width = 0;
layer->height = 0;
layer->fbo = 0;
layer->texture = 0;
if (Caches::getInstance().layerCache.resize(layer, width, height)) {
layer->layer.set(0.0f, 0.0f, width, height);
layer->texCoords.set(0.0f, height / float(layer->height),
width / float(layer->width), 0.0f);
} else {
if (layer->texture) glDeleteTextures(1, &layer->texture);
delete layer;
return false;
}
layer->width = width;
layer->height = height;
}
return true;
}
@@ -255,10 +241,16 @@ void LayerRenderer::destroyLayer(Layer* layer) {
if (layer) {
LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
if (layer->texture) glDeleteTextures(1, &layer->texture);
if (layer->fbo) {
Caches::getInstance().fboCache.put(layer->fbo);
}
delete layer;
if (!Caches::getInstance().layerCache.put(layer)) {
if (layer->texture) glDeleteTextures(1, &layer->texture);
delete layer;
} else {
layer->region.clear();
}
}
}

View File

@@ -64,14 +64,14 @@ enum DebugLevel {
// Converts a number of mega-bytes into bytes
#define MB(s) s * 1024 * 1024
#define DEFAULT_TEXTURE_CACHE_SIZE 20.0f
#define DEFAULT_LAYER_CACHE_SIZE 8.0f
#define DEFAULT_TEXTURE_CACHE_SIZE 24.0f
#define DEFAULT_LAYER_CACHE_SIZE 24.0f
#define DEFAULT_PATH_CACHE_SIZE 4.0f
#define DEFAULT_SHAPE_CACHE_SIZE 1.0f
#define DEFAULT_PATCH_CACHE_SIZE 512
#define DEFAULT_GRADIENT_CACHE_SIZE 0.5f
#define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f
#define DEFAULT_FBO_CACHE_SIZE 12
#define DEFAULT_FBO_CACHE_SIZE 16
#define DEFAULT_TEXT_GAMMA 1.4f
#define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64

View File

@@ -96,7 +96,16 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ViewLayersActivity6"
android:label="_ViewLayers6">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="AlphaLayersActivity"
android:label="_αLayers">

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<Button
android:onClick="enableLayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enable layer" />
<Button
android:onClick="disableLayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disable layer" />
<Button
android:onClick="shrinkLayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Shrink layer" />
<Button
android:onClick="growLayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Grow layer" />
</LinearLayout>
<ListView
android:id="@+id/list1"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2011 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.
*/
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
@SuppressWarnings({"UnusedDeclaration"})
public class ViewLayersActivity6 extends Activity {
private final Paint mPaint = new Paint();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_layers_6);
mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
setupList(R.id.list1);
}
public void enableLayer(View v) {
findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
}
public void disableLayer(View v) {
findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
}
public void growLayer(View v) {
findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
findViewById(R.id.list1).requestLayout();
}
public void shrinkLayer(View v) {
findViewById(R.id.list1).getLayoutParams().height = 300;
findViewById(R.id.list1).requestLayout();
}
private void setupList(int listId) {
final ListView list = (ListView) findViewById(listId);
list.setAdapter(new SimpleListAdapter(this));
}
private static class SimpleListAdapter extends ArrayAdapter<String> {
public SimpleListAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1, DATA_LIST);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = (TextView) super.getView(position, convertView, parent);
final Resources r = getContext().getResources();
final DisplayMetrics metrics = r.getDisplayMetrics();
v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
null, null, null);
return v;
}
}
private static final String[] DATA_LIST = {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
"Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
"Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
"Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
"Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
"Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
"British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
"Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
"Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
"Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
"Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
"Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
"East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
"Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
"Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
"French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
"Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
"Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
"Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
"Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
"Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
"Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
"Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
"Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
"Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
"Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
"Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
"Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
"Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
"Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
"Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
"Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
"Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
"Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
"Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
"The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
"Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
"Ukraine", "United Arab Emirates", "United Kingdom",
"United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
"Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
"Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
};
}