Loading libs/hwui/Tonemapper.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -97,7 +97,6 @@ void tonemapPaint(const SkImageInfo& source, const SkImageInfo& destination, flo .inputDataspace = sourceDataspace, .outputDataspace = destinationDataspace, .undoPremultipliedAlpha = source.alphaType() == kPremul_SkAlphaType, .fakeInputDataspace = destinationDataspace, .type = shaders::LinearEffect::SkSLType::ColorFilter}; constexpr float kMaxDisplayBrightnessNits = 1000.f; constexpr float kCurrentDisplayBrightnessNits = 500.f; Loading libs/hwui/utils/Color.cpp +5 −3 Original line number Diff line number Diff line Loading @@ -284,7 +284,9 @@ sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) { case HAL_DATASPACE_TRANSFER_GAMMA2_8: return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut); case HAL_DATASPACE_TRANSFER_ST2084: return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut); return SkColorSpace::MakeRGB({-2.0, -1.555223, 1.860454, 32 / 2523.0, 2413 / 128.0, -2392 / 128.0, 8192 / 1305.0}, gamut); case HAL_DATASPACE_TRANSFER_SMPTE_170M: return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut); case HAL_DATASPACE_TRANSFER_UNSPECIFIED: Loading Loading @@ -427,10 +429,10 @@ skcms_TransferFunction GetExtendedTransferFunction(float sdrHdrRatio) { } // Skia skcms' default HLG maps encoded [0, 1] to linear [1, 12] in order to follow ARIB // but LinearEffect expects a decoded [0, 1] range instead to follow Rec 2100. // but LinearEffect expects to map 1.0 == 203 nits std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction() { skcms_TransferFunction hlgFn; if (skcms_TransferFunction_makeScaledHLGish(&hlgFn, 1.f / 12.f, 2.f, 2.f, 1.f / 0.17883277f, if (skcms_TransferFunction_makeScaledHLGish(&hlgFn, 0.314509843, 2.f, 2.f, 1.f / 0.17883277f, 0.28466892f, 0.55991073f)) { return std::make_optional<skcms_TransferFunction>(hlgFn); } Loading tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java +151 −32 Original line number Diff line number Diff line Loading @@ -26,39 +26,57 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.RenderNode; import android.graphics.Shader; import android.graphics.SurfaceTexture; import android.hardware.HardwareBuffer; import android.media.Image; import android.media.ImageWriter; import android.os.Bundle; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.NonNull; import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; @SuppressWarnings({"UnusedDeclaration"}) public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callback, AdapterView.OnItemSelectedListener { TextureView.SurfaceTextureListener { private static final int WIDTH = 512; private static final int HEIGHT = 512; private ImageView mImageView; private SurfaceView mSurfaceView; private TextureView mTextureView; private HardwareBuffer mGradientBuffer; private ImageWriter mImageWriter; private Map<View, ImageWriter> mImageWriters = new HashMap<>(); private ColorSpace mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); private String[] mColorNames = {"sRGB", "BT2020_HLG", "BT2020_PQ"}; private String mCurrentColorName = "sRGB"; private FutureTask<HardwareBuffer> authorGradientBuffer(HardwareBuffer buffer) { private int mGradientEndColor = 0xFFFFFFFF; private int[] mGradientEndColors = {0xFFFFFFFF, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF}; private String[] mGradientColorNames = {"Grayscale", "Red", "Green", "Blue"}; private final ExecutorService mBufferFenceExecutor = Executors.newFixedThreadPool(1); private final ExecutorService mBufferExecutor = Executors.newFixedThreadPool(1); private FutureTask<HardwareBuffer> authorGradientBuffer( HardwareBuffer buffer, int gradentEndColor) { HardwareBufferRenderer renderer = new HardwareBufferRenderer(buffer); RenderNode node = new RenderNode("content"); node.setPosition(0, 0, buffer.getWidth(), buffer.getHeight()); Loading @@ -66,9 +84,10 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb Canvas canvas = node.beginRecording(); LinearGradient gradient = new LinearGradient( 0, 0, buffer.getWidth(), buffer.getHeight(), 0xFF000000, 0xFFFFFFFF, Shader.TileMode.CLAMP); gradentEndColor, Shader.TileMode.CLAMP); Paint paint = new Paint(); paint.setShader(gradient); paint.setDither(true); canvas.drawRect(0f, 0f, buffer.getWidth(), buffer.getHeight(), paint); node.endRecording(); Loading @@ -78,7 +97,7 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb FutureTask<HardwareBuffer> resolvedBuffer = new FutureTask<>(() -> buffer); renderer.obtainRenderRequest() .setColorSpace(colorSpace) .draw(Executors.newSingleThreadExecutor(), result -> { .draw(mBufferFenceExecutor, result -> { result.getFence().await(Duration.ofSeconds(3)); resolvedBuffer.run(); }); Loading @@ -90,7 +109,7 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb WIDTH, HEIGHT, PixelFormat.RGBA_8888, 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT); return authorGradientBuffer(buffer); return authorGradientBuffer(buffer, mGradientEndColor); } @Override Loading @@ -101,29 +120,70 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); ArrayAdapter<String> adapter = new ArrayAdapter<>( ArrayAdapter<String> colorSpaceAdapter = new ArrayAdapter<>( this, android.R.layout.simple_spinner_item, mColorNames); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner spinner = new Spinner(this); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); colorSpaceAdapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner colorSpaceSpinner = new Spinner(this); colorSpaceSpinner.setAdapter(colorSpaceAdapter); colorSpaceSpinner.setOnItemSelectedListener(new ColorSpaceOnItemSelectedListener()); ArrayAdapter<String> gradientColorAdapter = new ArrayAdapter<>( this, android.R.layout.simple_spinner_item, mGradientColorNames); gradientColorAdapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner gradientColorSpinner = new Spinner(this); gradientColorSpinner.setAdapter(gradientColorAdapter); gradientColorSpinner .setOnItemSelectedListener(new GradientColorOnItemSelectedListener()); mGradientBuffer = getGradientBuffer().get(); LinearLayout linearLayout = new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); TextView imageViewText = new TextView(this); imageViewText.setText("ImageView"); mImageView = new ImageView(this); TextView textureViewText = new TextView(this); textureViewText.setText("TextureView"); mTextureView = new TextureView(this); mTextureView.setSurfaceTextureListener(this); TextView surfaceViewText = new TextView(this); surfaceViewText.setText("SurfaceView"); mSurfaceView = new SurfaceView(this); mSurfaceView.getHolder().addCallback(this); linearLayout.addView(spinner, new LinearLayout.LayoutParams( LinearLayout spinnerLayout = new LinearLayout(this); spinnerLayout.setOrientation(LinearLayout.HORIZONTAL); spinnerLayout.addView(colorSpaceSpinner, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); spinnerLayout.addView(gradientColorSpinner, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(spinnerLayout, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(imageViewText, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(mImageView, new LinearLayout.LayoutParams(WIDTH, HEIGHT)); linearLayout.addView(textureViewText, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(mTextureView, new LinearLayout.LayoutParams(WIDTH, HEIGHT)); linearLayout.addView(surfaceViewText, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(mSurfaceView, new LinearLayout.LayoutParams(WIDTH, HEIGHT)); setContentView(linearLayout); Loading @@ -145,16 +205,24 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb } private void populateBuffers() { try { Bitmap bitmap = Bitmap.wrapHardwareBuffer( mGradientBuffer, ColorSpace.get(ColorSpace.Named.SRGB)); getGradientBuffer().get(), ColorSpace.get(ColorSpace.Named.SRGB)); Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, false); copy.setColorSpace(mColorSpace); mImageView.setImageBitmap(copy); try (Image image = mImageWriter.dequeueInputImage()) { authorGradientBuffer(image.getHardwareBuffer()).get(); for (ImageWriter writer : mImageWriters.values()) { mBufferExecutor.execute(() -> { try (Image image = writer.dequeueInputImage()) { authorGradientBuffer(image.getHardwareBuffer(), mGradientEndColor).get(); image.setDataSpace(mColorSpace.getDataSpace()); mImageWriter.queueInputImage(image); writer.queueInputImage(image); } catch (Exception e) { throw new RuntimeException(e); } }); } } catch (Exception e) { throw new RuntimeException(e); } Loading @@ -167,26 +235,76 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mImageWriter = new ImageWriter.Builder(holder.getSurface()) mImageWriters.put(mSurfaceView, new ImageWriter.Builder(holder.getSurface()) .setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | HardwareBuffer.USAGE_COMPOSER_OVERLAY) .build(); .build()); populateBuffers(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mImageWriter.close(); mImageWriter = null; if (mImageWriters.containsKey(mSurfaceView)) { mImageWriters.remove(mSurfaceView); } } @Override public void onSurfaceTextureAvailable( @NonNull SurfaceTexture surface, int width, int height) { mImageWriters.put(mTextureView, new ImageWriter.Builder(new Surface(surface)) .setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT) .build()); populateBuffers(); } @Override public void onSurfaceTextureSizeChanged( @NonNull SurfaceTexture surface, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) { if (mImageWriters.containsKey(mTextureView)) { mImageWriters.remove(mTextureView); } return false; } @Override public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) { } private final class ColorSpaceOnItemSelectedListener implements AdapterView.OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { mCurrentColorName = mColorNames[position]; mColorSpace = getFromName(mCurrentColorName); populateBuffers(); ColorBitmapActivity.this.mColorSpace = getFromName(ColorBitmapActivity.this.mColorNames[position]); ColorBitmapActivity.this.getMainExecutor() .execute(ColorBitmapActivity.this::populateBuffers); } @Override public void onNothingSelected(AdapterView<?> parent) { } } private final class GradientColorOnItemSelectedListener implements AdapterView.OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { ColorBitmapActivity.this.mGradientEndColor = ColorBitmapActivity.this.mGradientEndColors[position]; ColorBitmapActivity.this.getMainExecutor() .execute(ColorBitmapActivity.this::populateBuffers); } @Override Loading @@ -194,3 +312,4 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb } } } Loading
libs/hwui/Tonemapper.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -97,7 +97,6 @@ void tonemapPaint(const SkImageInfo& source, const SkImageInfo& destination, flo .inputDataspace = sourceDataspace, .outputDataspace = destinationDataspace, .undoPremultipliedAlpha = source.alphaType() == kPremul_SkAlphaType, .fakeInputDataspace = destinationDataspace, .type = shaders::LinearEffect::SkSLType::ColorFilter}; constexpr float kMaxDisplayBrightnessNits = 1000.f; constexpr float kCurrentDisplayBrightnessNits = 500.f; Loading
libs/hwui/utils/Color.cpp +5 −3 Original line number Diff line number Diff line Loading @@ -284,7 +284,9 @@ sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) { case HAL_DATASPACE_TRANSFER_GAMMA2_8: return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut); case HAL_DATASPACE_TRANSFER_ST2084: return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut); return SkColorSpace::MakeRGB({-2.0, -1.555223, 1.860454, 32 / 2523.0, 2413 / 128.0, -2392 / 128.0, 8192 / 1305.0}, gamut); case HAL_DATASPACE_TRANSFER_SMPTE_170M: return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut); case HAL_DATASPACE_TRANSFER_UNSPECIFIED: Loading Loading @@ -427,10 +429,10 @@ skcms_TransferFunction GetExtendedTransferFunction(float sdrHdrRatio) { } // Skia skcms' default HLG maps encoded [0, 1] to linear [1, 12] in order to follow ARIB // but LinearEffect expects a decoded [0, 1] range instead to follow Rec 2100. // but LinearEffect expects to map 1.0 == 203 nits std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction() { skcms_TransferFunction hlgFn; if (skcms_TransferFunction_makeScaledHLGish(&hlgFn, 1.f / 12.f, 2.f, 2.f, 1.f / 0.17883277f, if (skcms_TransferFunction_makeScaledHLGish(&hlgFn, 0.314509843, 2.f, 2.f, 1.f / 0.17883277f, 0.28466892f, 0.55991073f)) { return std::make_optional<skcms_TransferFunction>(hlgFn); } Loading
tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java +151 −32 Original line number Diff line number Diff line Loading @@ -26,39 +26,57 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.RenderNode; import android.graphics.Shader; import android.graphics.SurfaceTexture; import android.hardware.HardwareBuffer; import android.media.Image; import android.media.ImageWriter; import android.os.Bundle; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.NonNull; import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; @SuppressWarnings({"UnusedDeclaration"}) public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callback, AdapterView.OnItemSelectedListener { TextureView.SurfaceTextureListener { private static final int WIDTH = 512; private static final int HEIGHT = 512; private ImageView mImageView; private SurfaceView mSurfaceView; private TextureView mTextureView; private HardwareBuffer mGradientBuffer; private ImageWriter mImageWriter; private Map<View, ImageWriter> mImageWriters = new HashMap<>(); private ColorSpace mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); private String[] mColorNames = {"sRGB", "BT2020_HLG", "BT2020_PQ"}; private String mCurrentColorName = "sRGB"; private FutureTask<HardwareBuffer> authorGradientBuffer(HardwareBuffer buffer) { private int mGradientEndColor = 0xFFFFFFFF; private int[] mGradientEndColors = {0xFFFFFFFF, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF}; private String[] mGradientColorNames = {"Grayscale", "Red", "Green", "Blue"}; private final ExecutorService mBufferFenceExecutor = Executors.newFixedThreadPool(1); private final ExecutorService mBufferExecutor = Executors.newFixedThreadPool(1); private FutureTask<HardwareBuffer> authorGradientBuffer( HardwareBuffer buffer, int gradentEndColor) { HardwareBufferRenderer renderer = new HardwareBufferRenderer(buffer); RenderNode node = new RenderNode("content"); node.setPosition(0, 0, buffer.getWidth(), buffer.getHeight()); Loading @@ -66,9 +84,10 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb Canvas canvas = node.beginRecording(); LinearGradient gradient = new LinearGradient( 0, 0, buffer.getWidth(), buffer.getHeight(), 0xFF000000, 0xFFFFFFFF, Shader.TileMode.CLAMP); gradentEndColor, Shader.TileMode.CLAMP); Paint paint = new Paint(); paint.setShader(gradient); paint.setDither(true); canvas.drawRect(0f, 0f, buffer.getWidth(), buffer.getHeight(), paint); node.endRecording(); Loading @@ -78,7 +97,7 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb FutureTask<HardwareBuffer> resolvedBuffer = new FutureTask<>(() -> buffer); renderer.obtainRenderRequest() .setColorSpace(colorSpace) .draw(Executors.newSingleThreadExecutor(), result -> { .draw(mBufferFenceExecutor, result -> { result.getFence().await(Duration.ofSeconds(3)); resolvedBuffer.run(); }); Loading @@ -90,7 +109,7 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb WIDTH, HEIGHT, PixelFormat.RGBA_8888, 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT); return authorGradientBuffer(buffer); return authorGradientBuffer(buffer, mGradientEndColor); } @Override Loading @@ -101,29 +120,70 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); ArrayAdapter<String> adapter = new ArrayAdapter<>( ArrayAdapter<String> colorSpaceAdapter = new ArrayAdapter<>( this, android.R.layout.simple_spinner_item, mColorNames); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner spinner = new Spinner(this); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); colorSpaceAdapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner colorSpaceSpinner = new Spinner(this); colorSpaceSpinner.setAdapter(colorSpaceAdapter); colorSpaceSpinner.setOnItemSelectedListener(new ColorSpaceOnItemSelectedListener()); ArrayAdapter<String> gradientColorAdapter = new ArrayAdapter<>( this, android.R.layout.simple_spinner_item, mGradientColorNames); gradientColorAdapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner gradientColorSpinner = new Spinner(this); gradientColorSpinner.setAdapter(gradientColorAdapter); gradientColorSpinner .setOnItemSelectedListener(new GradientColorOnItemSelectedListener()); mGradientBuffer = getGradientBuffer().get(); LinearLayout linearLayout = new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); TextView imageViewText = new TextView(this); imageViewText.setText("ImageView"); mImageView = new ImageView(this); TextView textureViewText = new TextView(this); textureViewText.setText("TextureView"); mTextureView = new TextureView(this); mTextureView.setSurfaceTextureListener(this); TextView surfaceViewText = new TextView(this); surfaceViewText.setText("SurfaceView"); mSurfaceView = new SurfaceView(this); mSurfaceView.getHolder().addCallback(this); linearLayout.addView(spinner, new LinearLayout.LayoutParams( LinearLayout spinnerLayout = new LinearLayout(this); spinnerLayout.setOrientation(LinearLayout.HORIZONTAL); spinnerLayout.addView(colorSpaceSpinner, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); spinnerLayout.addView(gradientColorSpinner, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(spinnerLayout, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(imageViewText, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(mImageView, new LinearLayout.LayoutParams(WIDTH, HEIGHT)); linearLayout.addView(textureViewText, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(mTextureView, new LinearLayout.LayoutParams(WIDTH, HEIGHT)); linearLayout.addView(surfaceViewText, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); linearLayout.addView(mSurfaceView, new LinearLayout.LayoutParams(WIDTH, HEIGHT)); setContentView(linearLayout); Loading @@ -145,16 +205,24 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb } private void populateBuffers() { try { Bitmap bitmap = Bitmap.wrapHardwareBuffer( mGradientBuffer, ColorSpace.get(ColorSpace.Named.SRGB)); getGradientBuffer().get(), ColorSpace.get(ColorSpace.Named.SRGB)); Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, false); copy.setColorSpace(mColorSpace); mImageView.setImageBitmap(copy); try (Image image = mImageWriter.dequeueInputImage()) { authorGradientBuffer(image.getHardwareBuffer()).get(); for (ImageWriter writer : mImageWriters.values()) { mBufferExecutor.execute(() -> { try (Image image = writer.dequeueInputImage()) { authorGradientBuffer(image.getHardwareBuffer(), mGradientEndColor).get(); image.setDataSpace(mColorSpace.getDataSpace()); mImageWriter.queueInputImage(image); writer.queueInputImage(image); } catch (Exception e) { throw new RuntimeException(e); } }); } } catch (Exception e) { throw new RuntimeException(e); } Loading @@ -167,26 +235,76 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mImageWriter = new ImageWriter.Builder(holder.getSurface()) mImageWriters.put(mSurfaceView, new ImageWriter.Builder(holder.getSurface()) .setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | HardwareBuffer.USAGE_COMPOSER_OVERLAY) .build(); .build()); populateBuffers(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mImageWriter.close(); mImageWriter = null; if (mImageWriters.containsKey(mSurfaceView)) { mImageWriters.remove(mSurfaceView); } } @Override public void onSurfaceTextureAvailable( @NonNull SurfaceTexture surface, int width, int height) { mImageWriters.put(mTextureView, new ImageWriter.Builder(new Surface(surface)) .setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT) .build()); populateBuffers(); } @Override public void onSurfaceTextureSizeChanged( @NonNull SurfaceTexture surface, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) { if (mImageWriters.containsKey(mTextureView)) { mImageWriters.remove(mTextureView); } return false; } @Override public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) { } private final class ColorSpaceOnItemSelectedListener implements AdapterView.OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { mCurrentColorName = mColorNames[position]; mColorSpace = getFromName(mCurrentColorName); populateBuffers(); ColorBitmapActivity.this.mColorSpace = getFromName(ColorBitmapActivity.this.mColorNames[position]); ColorBitmapActivity.this.getMainExecutor() .execute(ColorBitmapActivity.this::populateBuffers); } @Override public void onNothingSelected(AdapterView<?> parent) { } } private final class GradientColorOnItemSelectedListener implements AdapterView.OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { ColorBitmapActivity.this.mGradientEndColor = ColorBitmapActivity.this.mGradientEndColors[position]; ColorBitmapActivity.this.getMainExecutor() .execute(ColorBitmapActivity.this::populateBuffers); } @Override Loading @@ -194,3 +312,4 @@ public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callb } } }