blob: 5b2adbf9c2c318a9535c4786feb1bf9c10d68c32 [file] [log] [blame]
Stan Iliev500a0c32016-10-26 10:30:09 -04001/*
2 * Copyright (C) 2016 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#include "SkiaOpenGLPipeline.h"
18
19#include "DeferredLayerUpdater.h"
Greg Daniel8cd3edf2017-01-09 14:15:41 -050020#include "GlLayer.h"
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -050021#include "LayerDrawable.h"
Matt Sarettcf2c05c2016-10-26 11:03:23 -040022#include "SkiaPipeline.h"
23#include "SkiaProfileRenderer.h"
John Reck1bcacfd2017-11-03 10:12:19 -070024#include "hwui/Bitmap.h"
25#include "renderstate/RenderState.h"
26#include "renderthread/EglManager.h"
27#include "renderthread/Frame.h"
Stan Iliev500a0c32016-10-26 10:30:09 -040028#include "utils/TraceUtils.h"
29
Greg Danielac2d2322017-07-12 11:30:15 -040030#include <GrBackendSurface.h>
31
Stan Iliev500a0c32016-10-26 10:30:09 -040032#include <cutils/properties.h>
33#include <strings.h>
34
35using namespace android::uirenderer::renderthread;
36
37namespace android {
38namespace uirenderer {
39namespace skiapipeline {
40
41SkiaOpenGLPipeline::SkiaOpenGLPipeline(RenderThread& thread)
John Reck1bcacfd2017-11-03 10:12:19 -070042 : SkiaPipeline(thread), mEglManager(thread.eglManager()) {}
Stan Iliev500a0c32016-10-26 10:30:09 -040043
44MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
45 // TODO: Figure out why this workaround is needed, see b/13913604
46 // In the meantime this matches the behavior of GLRenderer, so it is not a regression
47 EGLint error = 0;
48 if (!mEglManager.makeCurrent(mEglSurface, &error)) {
49 return MakeCurrentResult::AlreadyCurrent;
50 }
51 return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded;
52}
53
54Frame SkiaOpenGLPipeline::getFrame() {
55 LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
John Reck1bcacfd2017-11-03 10:12:19 -070056 "drawRenderNode called on a context with no surface!");
Stan Iliev500a0c32016-10-26 10:30:09 -040057 return mEglManager.beginFrame(mEglSurface);
58}
59
John Reck1bcacfd2017-11-03 10:12:19 -070060bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
61 const FrameBuilder::LightGeometry& lightGeometry,
62 LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
63 bool opaque, bool wideColorGamut,
64 const BakedOpRenderer::LightInfo& lightInfo,
65 const std::vector<sp<RenderNode>>& renderNodes,
66 FrameInfoVisualizer* profiler) {
Stan Iliev500a0c32016-10-26 10:30:09 -040067 mEglManager.damageFrame(frame, dirty);
68
Greg Danielc9da8e82018-03-21 10:50:24 -040069 SkColorType colorType;
Stan Iliev500a0c32016-10-26 10:30:09 -040070 // setup surface for fbo0
Greg Danielac2d2322017-07-12 11:30:15 -040071 GrGLFramebufferInfo fboInfo;
72 fboInfo.fFBOID = 0;
Greg Danielc9da8e82018-03-21 10:50:24 -040073 if (wideColorGamut) {
74 fboInfo.fFormat = GL_RGBA16F;
75 colorType = kRGBA_F16_SkColorType;
76 } else {
77 fboInfo.fFormat = GL_RGBA8;
78 colorType = kN32_SkColorType;
79 }
Greg Danielac2d2322017-07-12 11:30:15 -040080
Greg Danielc9da8e82018-03-21 10:50:24 -040081 GrBackendRenderTarget backendRT(frame.width(), frame.height(), 0, STENCIL_BUFFER_SIZE, fboInfo);
Stan Iliev500a0c32016-10-26 10:30:09 -040082
83 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
84
85 SkASSERT(mRenderThread.getGrContext() != nullptr);
86 sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(
Greg Danielc9da8e82018-03-21 10:50:24 -040087 mRenderThread.getGrContext(), backendRT, kBottomLeft_GrSurfaceOrigin, colorType,
88 nullptr, &props));
Stan Iliev500a0c32016-10-26 10:30:09 -040089
90 SkiaPipeline::updateLighting(lightGeometry, lightInfo);
John Reck1bcacfd2017-11-03 10:12:19 -070091 renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut, contentDrawBounds,
92 surface);
Stan Iliev500a0c32016-10-26 10:30:09 -040093 layerUpdateQueue->clear();
Matt Sarettcf2c05c2016-10-26 11:03:23 -040094
95 // Draw visual debugging features
John Reck1bcacfd2017-11-03 10:12:19 -070096 if (CC_UNLIKELY(Properties::showDirtyRegions ||
97 ProfileType::None != Properties::getProfileType())) {
Matt Sarettcf2c05c2016-10-26 11:03:23 -040098 SkCanvas* profileCanvas = surface->getCanvas();
99 SkiaProfileRenderer profileRenderer(profileCanvas);
100 profiler->draw(profileRenderer);
101 profileCanvas->flush();
102 }
103
Matt Sarett4bda6bf2016-11-07 15:43:41 -0500104 // Log memory statistics
105 if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
106 dumpResourceCacheUsage();
107 }
108
Stan Iliev500a0c32016-10-26 10:30:09 -0400109 return true;
110}
111
John Reck1bcacfd2017-11-03 10:12:19 -0700112bool SkiaOpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
113 FrameInfo* currentFrameInfo, bool* requireSwap) {
Stan Iliev500a0c32016-10-26 10:30:09 -0400114 GL_CHECKPOINT(LOW);
115
116 // Even if we decided to cancel the frame, from the perspective of jank
117 // metrics the frame was swapped at this point
118 currentFrameInfo->markSwapBuffers();
119
120 *requireSwap = drew || mEglManager.damageRequiresSwap();
121
122 if (*requireSwap && (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty)))) {
123 return false;
124 }
125
126 return *requireSwap;
127}
128
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500129bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
130 if (!mRenderThread.getGrContext()) {
131 return false;
132 }
133
Chris Craik2f1aaf72017-02-14 13:01:42 -0800134 // acquire most recent buffer for drawing
135 deferredLayer->updateTexImage();
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500136 deferredLayer->apply();
137
Derek Sollenberger4170db32017-08-09 13:52:36 -0400138 /* This intermediate surface is present to work around a bug in SwiftShader that
139 * prevents us from reading the contents of the layer's texture directly. The
140 * workaround involves first rendering that texture into an intermediate buffer and
141 * then reading from the intermediate buffer into the bitmap.
142 */
143 sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
John Reck1bcacfd2017-11-03 10:12:19 -0700144 SkBudgeted::kYes, bitmap->info());
Derek Sollenberger4170db32017-08-09 13:52:36 -0400145
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500146 Layer* layer = deferredLayer->backingLayer();
Leon Scroggins III1a12ab22018-03-26 15:00:49 -0400147 const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height());
148 if (LayerDrawable::DrawLayer(mRenderThread.getGrContext(), tmpSurface->getCanvas(), layer,
149 &dstRect)) {
Derek Sollenberger4170db32017-08-09 13:52:36 -0400150 sk_sp<SkImage> tmpImage = tmpSurface->makeImageSnapshot();
151 if (tmpImage->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
152 bitmap->notifyPixelsChanged();
153 return true;
154 }
155 }
156
157 return false;
Stan Iliev500a0c32016-10-26 10:30:09 -0400158}
159
sergeyv3e9999b2017-01-19 15:37:02 -0800160static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
John Reck1bcacfd2017-11-03 10:12:19 -0700161 SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
162 GlLayer* layer =
163 new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
sergeyv3e9999b2017-01-19 15:37:02 -0800164 layer->generateTexture();
165 return layer;
166}
167
Stan Iliev500a0c32016-10-26 10:30:09 -0400168DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
John Reck1e510712018-04-23 08:15:03 -0700169 mRenderThread.requireGlContext();
sergeyv3e9999b2017-01-19 15:37:02 -0800170 return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL);
Stan Iliev500a0c32016-10-26 10:30:09 -0400171}
172
173void SkiaOpenGLPipeline::onStop() {
174 if (mEglManager.isCurrent(mEglSurface)) {
175 mEglManager.makeCurrent(EGL_NO_SURFACE);
176 }
177}
178
Romain Guy26a2b972017-04-17 09:39:51 -0700179bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
John Reck1bcacfd2017-11-03 10:12:19 -0700180 ColorMode colorMode) {
Stan Iliev500a0c32016-10-26 10:30:09 -0400181 if (mEglSurface != EGL_NO_SURFACE) {
182 mEglManager.destroySurface(mEglSurface);
183 mEglSurface = EGL_NO_SURFACE;
184 }
185
186 if (surface) {
John Reck1e510712018-04-23 08:15:03 -0700187 mRenderThread.requireGlContext();
Romain Guy26a2b972017-04-17 09:39:51 -0700188 const bool wideColorGamut = colorMode == ColorMode::WideColorGamut;
189 mEglSurface = mEglManager.createSurface(surface, wideColorGamut);
Stan Iliev500a0c32016-10-26 10:30:09 -0400190 }
191
192 if (mEglSurface != EGL_NO_SURFACE) {
193 const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
194 mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
195 return true;
196 }
197
198 return false;
199}
200
201bool SkiaOpenGLPipeline::isSurfaceReady() {
202 return CC_UNLIKELY(mEglSurface != EGL_NO_SURFACE);
203}
204
205bool SkiaOpenGLPipeline::isContextReady() {
206 return CC_LIKELY(mEglManager.hasEglContext());
207}
208
209void SkiaOpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
210 DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
211 if (thread.eglManager().hasEglContext()) {
212 mode = DrawGlInfo::kModeProcess;
213 }
214
215 (*functor)(mode, nullptr);
216
217 // If there's no context we don't need to reset as there's no gl state to save/restore
218 if (mode != DrawGlInfo::kModeProcessNoContext) {
219 thread.getGrContext()->resetContext();
220 }
221}
222
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400223#define FENCE_TIMEOUT 2000000000
224
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400225class AutoEglImage {
226public:
John Reck1bcacfd2017-11-03 10:12:19 -0700227 AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer) : mDisplay(display) {
228 EGLint imageAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
229 image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer,
230 imageAttrs);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400231 }
232
233 ~AutoEglImage() {
234 if (image != EGL_NO_IMAGE_KHR) {
235 eglDestroyImageKHR(mDisplay, image);
236 }
237 }
238
239 EGLImageKHR image = EGL_NO_IMAGE_KHR;
John Reck1bcacfd2017-11-03 10:12:19 -0700240
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400241private:
242 EGLDisplay mDisplay = EGL_NO_DISPLAY;
243};
244
245class AutoSkiaGlTexture {
246public:
247 AutoSkiaGlTexture() {
248 glGenTextures(1, &mTexture);
249 glBindTexture(GL_TEXTURE_2D, mTexture);
250 }
251
John Reck1bcacfd2017-11-03 10:12:19 -0700252 ~AutoSkiaGlTexture() { glDeleteTextures(1, &mTexture); }
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400253
254private:
255 GLuint mTexture = 0;
256};
257
John Reckb90d4cb2018-04-19 17:05:35 -0700258struct FormatInfo {
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400259
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400260 PixelFormat pixelFormat;
261 GLint format, type;
262 bool isSupported = false;
John Reckb90d4cb2018-04-19 17:05:35 -0700263 bool valid = true;
264};
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400265
John Reckb90d4cb2018-04-19 17:05:35 -0700266static bool gpuSupportsHalfFloatTextures(renderthread::RenderThread& renderThread) {
267 static bool isSupported = renderThread.queue().runSync([&renderThread]() -> bool {
268 renderThread.requireGlContext();
269 sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
270 return grContext->colorTypeSupportedAsImage(kRGBA_F16_SkColorType);
271 });
272 return isSupported;
273}
274
275static FormatInfo determineFormat(renderthread::RenderThread& renderThread,
276 const SkBitmap& skBitmap) {
277 FormatInfo formatInfo;
John Reck1bcacfd2017-11-03 10:12:19 -0700278 // TODO: add support for linear blending (when ANDROID_ENABLE_LINEAR_BLENDING is defined)
John Reckb90d4cb2018-04-19 17:05:35 -0700279 switch (skBitmap.info().colorType()) {
John Reck1bcacfd2017-11-03 10:12:19 -0700280 case kRGBA_8888_SkColorType:
John Reckb90d4cb2018-04-19 17:05:35 -0700281 formatInfo.isSupported = true;
John Reck1bcacfd2017-11-03 10:12:19 -0700282 // ARGB_4444 is upconverted to RGBA_8888
283 case kARGB_4444_SkColorType:
John Reckb90d4cb2018-04-19 17:05:35 -0700284 formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_8888;
285 formatInfo.format = GL_RGBA;
286 formatInfo.type = GL_UNSIGNED_BYTE;
John Reck1bcacfd2017-11-03 10:12:19 -0700287 break;
288 case kRGBA_F16_SkColorType:
John Reckb90d4cb2018-04-19 17:05:35 -0700289 formatInfo.isSupported = gpuSupportsHalfFloatTextures(renderThread);
290 if (formatInfo.isSupported) {
291 formatInfo.type = GL_HALF_FLOAT;
292 formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_FP16;
John Reck1bcacfd2017-11-03 10:12:19 -0700293 } else {
John Reckb90d4cb2018-04-19 17:05:35 -0700294 formatInfo.type = GL_UNSIGNED_BYTE;
295 formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_8888;
John Reck1bcacfd2017-11-03 10:12:19 -0700296 }
John Reckb90d4cb2018-04-19 17:05:35 -0700297 formatInfo.format = GL_RGBA;
John Reck1bcacfd2017-11-03 10:12:19 -0700298 break;
299 case kRGB_565_SkColorType:
John Reckb90d4cb2018-04-19 17:05:35 -0700300 formatInfo.isSupported = true;
301 formatInfo.pixelFormat = PIXEL_FORMAT_RGB_565;
302 formatInfo.format = GL_RGB;
303 formatInfo.type = GL_UNSIGNED_SHORT_5_6_5;
John Reck1bcacfd2017-11-03 10:12:19 -0700304 break;
305 case kGray_8_SkColorType:
John Reckb90d4cb2018-04-19 17:05:35 -0700306 formatInfo.isSupported = true;
307 formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_8888;
308 formatInfo.format = GL_LUMINANCE;
309 formatInfo.type = GL_UNSIGNED_BYTE;
John Reck1bcacfd2017-11-03 10:12:19 -0700310 break;
311 default:
John Reckb90d4cb2018-04-19 17:05:35 -0700312 ALOGW("unable to create hardware bitmap of colortype: %d", skBitmap.info().colorType());
313 formatInfo.valid = false;
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400314 }
John Reckb90d4cb2018-04-19 17:05:35 -0700315 return formatInfo;
316}
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400317
John Reckb90d4cb2018-04-19 17:05:35 -0700318static SkBitmap makeHwCompatible(const FormatInfo& format, const SkBitmap& source) {
319 if (format.isSupported) {
320 return source;
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400321 } else {
John Reckb90d4cb2018-04-19 17:05:35 -0700322 SkBitmap bitmap;
323 const SkImageInfo& info = source.info();
John Reck1bcacfd2017-11-03 10:12:19 -0700324 bitmap.allocPixels(
325 SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType(), nullptr));
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400326 bitmap.eraseColor(0);
Derek Sollenbergerfb0c8fc2017-07-26 13:53:27 -0400327 if (info.colorType() == kRGBA_F16_SkColorType) {
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400328 // Drawing RGBA_F16 onto ARGB_8888 is not supported
John Reckb90d4cb2018-04-19 17:05:35 -0700329 source.readPixels(bitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()),
330 bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400331 } else {
332 SkCanvas canvas(bitmap);
John Reckb90d4cb2018-04-19 17:05:35 -0700333 canvas.drawBitmap(source, 0.0f, 0.0f, nullptr);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400334 }
John Reckb90d4cb2018-04-19 17:05:35 -0700335 return bitmap;
336 }
337}
338
339sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThread& thread,
340 const SkBitmap& sourceBitmap) {
341 ATRACE_CALL();
342
343 LOG_ALWAYS_FATAL_IF(thread.isCurrent(), "Must not be called on RenderThread");
344
345 FormatInfo format = determineFormat(thread, sourceBitmap);
346 if (!format.valid) {
347 return nullptr;
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400348 }
349
John Reckb90d4cb2018-04-19 17:05:35 -0700350 SkBitmap bitmap = makeHwCompatible(format, sourceBitmap);
John Reck1bcacfd2017-11-03 10:12:19 -0700351 sp<GraphicBuffer> buffer = new GraphicBuffer(
John Reckb90d4cb2018-04-19 17:05:35 -0700352 static_cast<uint32_t>(bitmap.width()), static_cast<uint32_t>(bitmap.height()),
353 format.pixelFormat,
John Reck1bcacfd2017-11-03 10:12:19 -0700354 GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
355 GraphicBuffer::USAGE_SW_READ_NEVER,
356 std::string("Bitmap::allocateSkiaHardwareBitmap pid [") + std::to_string(getpid()) +
357 "]");
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400358
359 status_t error = buffer->initCheck();
360 if (error < 0) {
361 ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
362 return nullptr;
363 }
364
John Reckb90d4cb2018-04-19 17:05:35 -0700365 EGLDisplay display = thread.queue().runSync([&]() -> EGLDisplay {
366 thread.requireGlContext();
367 return eglGetCurrentDisplay();
368 });
369
John Reck1bcacfd2017-11-03 10:12:19 -0700370 LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
371 uirenderer::renderthread::EglManager::eglErrorString());
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400372 // We use an EGLImage to access the content of the GraphicBuffer
373 // The EGL image is later bound to a 2D texture
John Reck1bcacfd2017-11-03 10:12:19 -0700374 EGLClientBuffer clientBuffer = (EGLClientBuffer)buffer->getNativeBuffer();
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400375 AutoEglImage autoImage(display, clientBuffer);
376 if (autoImage.image == EGL_NO_IMAGE_KHR) {
377 ALOGW("Could not create EGL image, err =%s",
John Reck1bcacfd2017-11-03 10:12:19 -0700378 uirenderer::renderthread::EglManager::eglErrorString());
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400379 return nullptr;
380 }
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400381
John Reckb90d4cb2018-04-19 17:05:35 -0700382 {
383 ATRACE_FORMAT("CPU -> gralloc transfer (%dx%d)", bitmap.width(), bitmap.height());
384 EGLSyncKHR fence = thread.queue().runSync([&]() -> EGLSyncKHR {
385 thread.requireGlContext();
386 sk_sp<GrContext> grContext = sk_ref_sp(thread.getGrContext());
387 AutoSkiaGlTexture glTexture;
388 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
389 GL_CHECKPOINT(MODERATE);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400390
John Reckb90d4cb2018-04-19 17:05:35 -0700391 // glTexSubImage2D is synchronous in sense that it memcpy() from pointer that we
392 // provide.
393 // But asynchronous in sense that driver may upload texture onto hardware buffer when we
394 // first
395 // use it in drawing
396 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), format.format,
397 format.type, bitmap.getPixels());
398 GL_CHECKPOINT(MODERATE);
399
400 EGLSyncKHR uploadFence =
401 eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_FENCE_KHR, NULL);
402 LOG_ALWAYS_FATAL_IF(uploadFence == EGL_NO_SYNC_KHR, "Could not create sync fence %#x",
403 eglGetError());
404 glFlush();
405 grContext->resetContext(kTextureBinding_GrGLBackendState);
406 return uploadFence;
407 });
408
409 EGLint waitStatus = eglClientWaitSyncKHR(display, fence, 0, FENCE_TIMEOUT);
410 LOG_ALWAYS_FATAL_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR,
411 "Failed to wait for the fence %#x", eglGetError());
412
413 eglDestroySyncKHR(display, fence);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400414 }
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400415
416 return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info()));
417}
418
Stan Iliev500a0c32016-10-26 10:30:09 -0400419} /* namespace skiapipeline */
420} /* namespace uirenderer */
421} /* namespace android */