1 /*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "common/rs_background_thread.h"
17 #include "pipeline/render_thread/rs_uni_render_processor.h"
18 #include "pipeline/render_thread/rs_uni_render_util.h"
19 #include "pipeline/sk_resource_manager.h"
20 #include "rs_magic_pointer_render_manager.h"
21 #include "rs_trace.h"
22 #include "src/gpu/gl/GrGLDefines.h"
23
24 namespace OHOS {
25 namespace Rosen {
26 namespace {
27 static const std::string DISPLAY = "DisplayNode";
28 static const std::string POINTER = "pointer";
29 static const float RGB = 255.0f;
30 static const float HALF = 0.5f;
31 static const float MIN_BUFFER_NUMBER = 0.0f;
32 static const float MAX_BUFFER_NUMBER = 1.0f;
33 static const int64_t MAX_INTERVAL_TIME = 1000;
34 static const int32_t MAX_RANGE_SIZE = 100;
35 static const int32_t CALCULATE_MIDDLE = 2;
36 } // namespace
37 static std::unique_ptr<RSMagicPointerRenderManager> g_pointerRenderManagerInstance =
38 std::make_unique<RSMagicPointerRenderManager>();
39
GetInstance()40 RSMagicPointerRenderManager& RSMagicPointerRenderManager::GetInstance()
41 {
42 return *g_pointerRenderManagerInstance;
43 }
44
45 #if defined (RS_ENABLE_VK)
InitInstance(const std::shared_ptr<RSVkImageManager> & vkImageManager)46 void RSMagicPointerRenderManager::InitInstance(const std::shared_ptr<RSVkImageManager>& vkImageManager)
47 {
48 g_pointerRenderManagerInstance->vkImageManager_ = vkImageManager;
49 }
50 #endif
51
52 #if defined (RS_ENABLE_GL) && defined (RS_ENABLE_EGLIMAGE)
InitInstance(const std::shared_ptr<RSEglImageManager> & eglImageManager)53 void RSMagicPointerRenderManager::InitInstance(const std::shared_ptr<RSEglImageManager>& eglImageManager)
54 {
55 g_pointerRenderManagerInstance->eglImageManager_ = eglImageManager;
56 }
57 #endif
58
GetCurrentTime()59 int64_t RSMagicPointerRenderManager::GetCurrentTime()
60 {
61 auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
62 return std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch()).count();
63 }
64
SetPointerColorInversionConfig(float darkBuffer,float brightBuffer,int64_t interval,int32_t rangeSize)65 void RSMagicPointerRenderManager::SetPointerColorInversionConfig(float darkBuffer, float brightBuffer,
66 int64_t interval, int32_t rangeSize)
67 {
68 std::lock_guard<std::mutex> locker(mtx_);
69 if (darkBuffer > MIN_BUFFER_NUMBER && darkBuffer < MAX_BUFFER_NUMBER) {
70 darkBuffer_ = darkBuffer;
71 }
72 if (brightBuffer > MIN_BUFFER_NUMBER && brightBuffer < MAX_BUFFER_NUMBER) {
73 brightBuffer_ = brightBuffer;
74 }
75 if (interval > 0 && interval < MAX_INTERVAL_TIME) {
76 colorSamplingInterval_ = interval;
77 }
78 if (rangeSize > 0 && rangeSize < MAX_RANGE_SIZE) {
79 rangeSize_ = rangeSize;
80 }
81 }
82
SetPointerColorInversionEnabled(bool enable)83 void RSMagicPointerRenderManager::SetPointerColorInversionEnabled(bool enable)
84 {
85 std::lock_guard<std::mutex> locker(mtx_);
86 isEnableCursorInversion_ = enable;
87 }
88
GetPointerColorInversionEnabled()89 bool RSMagicPointerRenderManager::GetPointerColorInversionEnabled()
90 {
91 std::lock_guard<std::mutex> locker(mtx_);
92 return isEnableCursorInversion_;
93 }
94
RegisterPointerLuminanceChangeCallback(pid_t pid,sptr<RSIPointerLuminanceChangeCallback> callback)95 void RSMagicPointerRenderManager::RegisterPointerLuminanceChangeCallback(pid_t pid,
96 sptr<RSIPointerLuminanceChangeCallback> callback)
97 {
98 std::lock_guard<std::mutex> locker(mtx_);
99 colorChangeListeners_[pid] = callback;
100 }
101
UnRegisterPointerLuminanceChangeCallback(pid_t pid)102 void RSMagicPointerRenderManager::UnRegisterPointerLuminanceChangeCallback(pid_t pid)
103 {
104 std::lock_guard<std::mutex> locker(mtx_);
105 colorChangeListeners_.erase(pid);
106 }
107
ExecutePointerLuminanceChangeCallback(int32_t brightness)108 void RSMagicPointerRenderManager::ExecutePointerLuminanceChangeCallback(int32_t brightness)
109 {
110 for (auto it = colorChangeListeners_.begin(); it != colorChangeListeners_.end(); it++) {
111 if (it->second) {
112 it->second->OnPointerLuminanceChanged(brightness);
113 }
114 }
115 }
116
CallPointerLuminanceChange(int32_t brightness)117 void RSMagicPointerRenderManager::CallPointerLuminanceChange(int32_t brightness)
118 {
119 RS_LOGD("RSMagicPointerRenderManager::CallPointerLuminanceChange brightness:%{public}d.", brightness);
120 lastColorPickerTime_ = RSMagicPointerRenderManager::GetCurrentTime();
121 if (brightnessMode_ == CursorBrightness::NONE) {
122 brightnessMode_ = brightness < static_cast<int32_t>(RGB * HALF) ?
123 CursorBrightness::DARK : CursorBrightness::BRIGHT;
124 ExecutePointerLuminanceChangeCallback(brightness);
125 } else if (brightnessMode_ == CursorBrightness::DARK) {
126 // Dark cursor to light cursor buffer
127 if (brightness > static_cast<int32_t>(RGB * darkBuffer_)) {
128 brightnessMode_ = CursorBrightness::BRIGHT;
129 ExecutePointerLuminanceChangeCallback(brightness);
130 }
131 } else {
132 // light cursor to Dark cursor buffer
133 if (brightness < static_cast<int32_t>(RGB * brightBuffer_)) {
134 brightnessMode_ = CursorBrightness::DARK;
135 ExecutePointerLuminanceChangeCallback(brightness);
136 }
137 }
138 }
139
CheckColorPickerEnabled()140 bool RSMagicPointerRenderManager::CheckColorPickerEnabled()
141 {
142 if (!isEnableCursorInversion_ || taskDoing_) {
143 return false;
144 }
145
146 auto time = RSMagicPointerRenderManager::GetCurrentTime() - lastColorPickerTime_;
147 if (time < colorSamplingInterval_) {
148 return false;
149 }
150
151 bool exists = false;
152 auto& threadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
153 if (threadParams == nullptr) {
154 ROSEN_LOGE("RSMagicPointerRenderManager::CheckColorPickerEnabled threadParams == nullptr");
155 return false;
156 }
157 const auto& hardwareDrawables = threadParams->GetHardwareEnabledTypeDrawables();
158
159 for (const auto& [_, drawable] : hardwareDrawables) {
160 if (drawable == nullptr) {
161 continue;
162 }
163 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
164 if (surfaceDrawable != nullptr && surfaceDrawable->IsHardwareEnabledTopSurface()) {
165 exists = true;
166 break;
167 }
168 }
169
170 return exists;
171 }
172
ProcessColorPicker(std::shared_ptr<RSProcessor> processor,std::shared_ptr<Drawing::GPUContext> gpuContext)173 void RSMagicPointerRenderManager::ProcessColorPicker(std::shared_ptr<RSProcessor> processor,
174 std::shared_ptr<Drawing::GPUContext> gpuContext)
175 {
176 if (!CheckColorPickerEnabled()) {
177 ROSEN_LOGD("RSMagicPointerRenderManager::CheckColorPickerEnabled is false!");
178 return;
179 }
180
181 RS_TRACE_BEGIN("RSMagicPointerRenderManager ProcessColorPicker");
182 std::lock_guard<std::mutex> locker(mtx_);
183
184 if (cacheImgForPointer_) {
185 if (!GetIntersectImageBySubset(gpuContext)) {
186 ROSEN_LOGE("RSMagicPointerRenderManager::GetIntersectImageBySubset is false!");
187 return;
188 }
189 } else {
190 if (!CalculateTargetLayer(processor)) { // get the layer intersect with pointer and calculate the rect
191 ROSEN_LOGD("RSMagicPointerRenderManager::CalculateTargetLayer is false!");
192 return;
193 }
194 }
195
196 // post color picker task to background thread
197 RunColorPickerTask();
198 RS_TRACE_END();
199 }
200
GetIntersectImageBySubset(std::shared_ptr<Drawing::GPUContext> gpuContext)201 bool RSMagicPointerRenderManager::GetIntersectImageBySubset(std::shared_ptr<Drawing::GPUContext> gpuContext)
202 {
203 if (gpuContext == nullptr) {
204 return false;
205 }
206 const auto& hardwareDrawables =
207 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
208 for (const auto& [_, drawable] : hardwareDrawables) {
209 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
210 if (surfaceDrawable == nullptr || !surfaceDrawable->IsHardwareEnabledTopSurface()) {
211 continue;
212 }
213 auto& surfaceParams = surfaceDrawable->GetRenderParams();
214 if (!surfaceParams) {
215 continue;
216 }
217 image_ = std::make_shared<Drawing::Image>();
218 RectI pointerRect = surfaceParams->GetAbsDrawRect();
219 CalculateColorRange(pointerRect);
220 Drawing::RectI drawingPointerRect = Drawing::RectI(pointerRect.GetLeft(), pointerRect.GetTop(),
221 pointerRect.GetRight(), pointerRect.GetBottom());
222 image_->BuildSubset(cacheImgForPointer_, drawingPointerRect, *gpuContext);
223
224 Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
225 backendTexture_ = image_->GetBackendTexture(false, &origin);
226 bitmapFormat_ = Drawing::BitmapFormat{ image_->GetColorType(), image_->GetAlphaType() };
227 return true;
228 }
229 return false;
230 }
231
CalculateTargetLayer(std::shared_ptr<RSProcessor> processor)232 bool RSMagicPointerRenderManager::CalculateTargetLayer(std::shared_ptr<RSProcessor> processor)
233 {
234 #ifdef RS_ENABLE_GPU
235 auto uniRenderProcessor = std::static_pointer_cast<RSUniRenderProcessor>(processor);
236 if (uniRenderProcessor == nullptr) {
237 ROSEN_LOGE("RSMagicPointerRenderManager::CalculateTargetLayer uniRenderProcessor is null!");
238 return false;
239 }
240 std::vector<LayerInfoPtr> layers = uniRenderProcessor->GetLayers();
241 forceCPU_ = RSBaseRenderEngine::NeedForceCPU(layers);
242
243 std::sort(layers.begin(), layers.end(), [](LayerInfoPtr a, LayerInfoPtr b) {
244 return a->GetZorder() < b->GetZorder();
245 });
246 // get pointer and display node layer
247 bool find = false;
248 RectI pRect;
249 int displayNodeIndex = INT_MAX;
250 for (int i = 0; i < static_cast<int>(layers.size()); ++i) {
251 std::string name = layers[i]->GetSurface()->GetName();
252 if (name.find(DISPLAY) != std::string::npos) {
253 displayNodeIndex = i;
254 continue;
255 }
256 if (name.find(POINTER) != std::string::npos) {
257 GraphicIRect rect = layers[i]->GetLayerSize();
258 pRect.SetAll(rect.x, rect.y, rect.w, rect.h);
259 find = true;
260 continue;
261 }
262 }
263
264 if (!find || displayNodeIndex == INT_MAX) {
265 ROSEN_LOGD("RSMagicPointerRenderManager::CalculateTargetLayer cannot find pointer or display node.");
266 return false;
267 }
268 CalculateColorRange(pRect);
269 // calculate the max intersection layer and rect
270 GetRectAndTargetLayer(layers, pRect, displayNodeIndex);
271 #endif
272 return true;
273 }
274
CalculateColorRange(RectI & pRect)275 void RSMagicPointerRenderManager::CalculateColorRange(RectI& pRect)
276 {
277 if (rangeSize_ > 0 && rangeSize_ < pRect.GetWidth() && rangeSize_ < pRect.GetHeight()) {
278 int left = pRect.GetLeft() + (pRect.GetWidth() - rangeSize_) / CALCULATE_MIDDLE;
279 int top = pRect.GetTop() + (pRect.GetHeight() - rangeSize_) / CALCULATE_MIDDLE;
280 pRect.SetAll(left, top, rangeSize_, rangeSize_);
281 }
282 }
283
GetRectAndTargetLayer(std::vector<LayerInfoPtr> & layers,RectI & pRect,int displayNodeIndex)284 void RSMagicPointerRenderManager::GetRectAndTargetLayer(std::vector<LayerInfoPtr>& layers, RectI& pRect,
285 int displayNodeIndex)
286 {
287 target_ = nullptr;
288 rect_.Clear();
289
290 for (int i = std::max(0, displayNodeIndex - 1); i >= 0; --i) {
291 if (layers[i]->GetSurface()->GetName().find(POINTER) != std::string::npos) {
292 continue;
293 }
294 GraphicIRect layerSize = layers[i]->GetLayerSize();
295 RectI curRect = RectI(layerSize.x, layerSize.y, layerSize.w, layerSize.h);
296 if (!curRect.Intersect(pRect)) {
297 continue;
298 }
299 RectI dstRect = curRect.IntersectRect(pRect);
300 if (dstRect.width_ * dstRect.height_ >= rect_.width_ * rect_.height_) {
301 rect_ = dstRect;
302 target_ = layers[i];
303 }
304 }
305
306 // if not intersect with other layers, calculate the displayNode intersection rect
307 if (target_ == nullptr) {
308 target_ = layers[displayNodeIndex];
309 GraphicIRect layerSize = target_->GetLayerSize();
310 RectI curRect = RectI(layerSize.x, layerSize.y, layerSize.w, layerSize.h);
311 RectI dstRect = curRect.IntersectRect(pRect);
312 }
313 }
314
CalcAverageLuminance(std::shared_ptr<Drawing::Image> image)315 int16_t RSMagicPointerRenderManager::CalcAverageLuminance(std::shared_ptr<Drawing::Image> image)
316 {
317 // create a 1x1 SkPixmap
318 uint32_t pixel[1] = { 0 };
319 Drawing::ImageInfo single_pixel_info(1, 1, Drawing::ColorType::COLORTYPE_RGBA_8888,
320 Drawing::AlphaType::ALPHATYPE_PREMUL);
321 Drawing::Bitmap single_pixel;
322 single_pixel.Build(single_pixel_info, single_pixel_info.GetBytesPerPixel());
323 single_pixel.SetPixels(pixel);
324
325 // resize image to 1x1 to calculate average color
326 // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
327 image->ScalePixels(single_pixel,
328 Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::LINEAR));
329 // convert color format and return average luminance
330 auto color = SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
331 return Drawing::Color::ColorQuadGetR(color) * 0.2126f + Drawing::Color::ColorQuadGetG(color) * 0.7152f +
332 Drawing::Color::ColorQuadGetB(color) * 0.0722f;
333 }
334
RunColorPickerTaskBackground(BufferDrawParam & param)335 void RSMagicPointerRenderManager::RunColorPickerTaskBackground(BufferDrawParam& param)
336 {
337 #ifdef RS_ENABLE_UNI_RENDER
338 std::lock_guard<std::mutex> locker(mtx_);
339 std::shared_ptr<Drawing::Image> image;
340 auto context = RSBackgroundThread::Instance().GetShareGPUContext().get();
341 if (backendTexturePre_.IsValid()) {
342 image = std::make_shared<Drawing::Image>();
343 SharedTextureContext* sharedContext = new SharedTextureContext(imagePre_);
344 bool ret = image->BuildFromTexture(*context, backendTexturePre_.GetTextureInfo(),
345 Drawing::TextureOrigin::BOTTOM_LEFT, bitmapFormat_, nullptr,
346 SKResourceManager::DeleteSharedTextureContext, sharedContext);
347 if (!ret) {
348 RS_LOGE("RSMagicPointerRenderManager::RunColorPickerTaskBackground BuildFromTexture failed.");
349 return;
350 }
351 } else {
352 image = GetIntersectImageByLayer(param);
353 }
354 if (image == nullptr || !image->IsValid(context)) {
355 RS_LOGE("RSMagicPointerRenderManager::RunColorPickerTaskBackground image not valid.");
356 return;
357 }
358
359 luminance_ = CalcAverageLuminance(image);
360
361 CallPointerLuminanceChange(luminance_);
362 #endif
363 }
364
RunColorPickerTask()365 void RSMagicPointerRenderManager::RunColorPickerTask()
366 {
367 if (!imagePre_ && (target_ == nullptr || rect_.IsEmpty())) {
368 ROSEN_LOGE("RSMagicPointerRenderManager::RunColorPickerTask failed for null target or rect is empty!");
369 return;
370 }
371
372 BufferDrawParam param;
373 if (!imagePre_) {
374 param = RSUniRenderUtil::CreateLayerBufferDrawParam(target_, forceCPU_);
375 }
376 RSBackgroundThread::Instance().PostTask([this, param] () mutable {
377 taskDoing_ = true;
378 this->RunColorPickerTaskBackground(param);
379 backendTexturePre_ = backendTexture_;
380 backendTexture_ = Drawing::BackendTexture(false);
381 imagePre_ = image_;
382 image_ = nullptr;
383 taskDoing_ = false;
384 });
385 }
386
GetIntersectImageByLayer(BufferDrawParam & param)387 std::shared_ptr<Drawing::Image> RSMagicPointerRenderManager::GetIntersectImageByLayer(BufferDrawParam& param)
388 {
389 #ifdef RS_ENABLE_UNI_RENDER
390 auto screenManager = CreateOrGetScreenManager();
391 if (screenManager == nullptr) {
392 RS_LOGE("RSPointerRenderManager::GetIntersectImageByLayer screenManager is null.");
393 return nullptr;
394 }
395 auto screenInfo = screenManager->QueryScreenInfo(param.screenId);
396 param.matrix.PostScale(screenInfo.GetRogWidthRatio(), screenInfo.GetRogHeightRatio());
397
398 Drawing::Matrix mat;
399 bool flag = param.matrix.Invert(mat);
400 if (!flag) {
401 RS_LOGE("RSPointerRenderManager::GetIntersectImageByLayer param.matrix not invert.");
402 return nullptr;
403 }
404 Drawing::Rect rectOrigin = Drawing::Rect(rect_.GetLeft(), rect_.GetTop(), rect_.GetRight(), rect_.GetBottom());
405 Drawing::Rect imgCutRectF;
406 mat.MapRect(imgCutRectF, rectOrigin);
407 Drawing::RectI imgCutRect = Drawing::RectI(imgCutRectF.GetLeft(), imgCutRectF.GetTop(), imgCutRectF.GetRight(),
408 imgCutRectF.GetBottom());
409 const auto context = RSBackgroundThread::Instance().GetShareGPUContext();
410 if (context == nullptr) {
411 RS_LOGE("RSMagicPointerRenderManager::GetIntersectImageByLayer context is nullptr.");
412 return nullptr;
413 }
414 if (param.buffer == nullptr) {
415 ROSEN_LOGE("RSMagicPointerRenderManager::GetIntersectImageByLayer param buffer is nullptr");
416 return nullptr;
417 }
418 #ifdef RS_ENABLE_VK
419 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN
420 || RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
421 return GetIntersectImageFromVK(imgCutRect, context, param);
422 }
423 #endif
424 #if defined(RS_ENABLE_GL) && defined(RS_ENABLE_EGLIMAGE)
425 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
426 return GetIntersectImageFromGL(imgCutRect, context, param);
427 }
428 #endif
429 #endif
430 return nullptr;
431 }
432
433 #ifdef RS_ENABLE_VK
GetIntersectImageFromVK(Drawing::RectI & imgCutRect,const std::shared_ptr<Drawing::GPUContext> & context,BufferDrawParam & param)434 std::shared_ptr<Drawing::Image> RSMagicPointerRenderManager::GetIntersectImageFromVK(Drawing::RectI& imgCutRect,
435 const std::shared_ptr<Drawing::GPUContext>& context, BufferDrawParam& param)
436 {
437 if (vkImageManager_ == nullptr) {
438 RS_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromVK vkImageManager_ == nullptr");
439 return nullptr;
440 }
441 auto imageCache = vkImageManager_->CreateImageCacheFromBuffer(param.buffer, param.acquireFence);
442 if (imageCache == nullptr) {
443 ROSEN_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromVK imageCache == nullptr!");
444 return nullptr;
445 }
446 auto& backendTexture = imageCache->GetBackendTexture();
447 Drawing::BitmapFormat bitmapFormat = RSBaseRenderUtil::GenerateDrawingBitmapFormat(param.buffer);
448
449 std::shared_ptr<Drawing::Image> layerImage = std::make_shared<Drawing::Image>();
450 if (!layerImage->BuildFromTexture(*context, backendTexture.GetTextureInfo(),
451 Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr,
452 NativeBufferUtils::DeleteVkImage, imageCache->RefCleanupHelper())) {
453 ROSEN_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromVK image BuildFromTexture failed.");
454 return nullptr;
455 }
456
457 std::shared_ptr<Drawing::Image> cutDownImage = std::make_shared<Drawing::Image>();
458 cutDownImage->BuildSubset(layerImage, imgCutRect, *context);
459 return cutDownImage;
460 }
461 #endif
462
463 #if defined (RS_ENABLE_GL) && defined (RS_ENABLE_EGLIMAGE)
GetIntersectImageFromGL(Drawing::RectI & imgCutRect,const std::shared_ptr<Drawing::GPUContext> & context,BufferDrawParam & param)464 std::shared_ptr<Drawing::Image> RSMagicPointerRenderManager::GetIntersectImageFromGL(Drawing::RectI& imgCutRect,
465 const std::shared_ptr<Drawing::GPUContext>& context, BufferDrawParam& param)
466 {
467 if (eglImageManager_ == nullptr) {
468 RS_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromGL eglImageManager_ == nullptr");
469 return nullptr;
470 }
471 auto eglTextureId = eglImageManager_->MapEglImageFromSurfaceBuffer(param.buffer,
472 param.acquireFence, param.threadIndex);
473 if (eglTextureId == 0) {
474 RS_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromGL invalid texture ID");
475 return nullptr;
476 }
477
478 Drawing::BitmapFormat bitmapFormat = RSBaseRenderUtil::GenerateDrawingBitmapFormat(param.buffer);
479 Drawing::TextureInfo externalTextureInfo;
480 externalTextureInfo.SetWidth(param.buffer->GetSurfaceBufferWidth());
481 externalTextureInfo.SetHeight(param.buffer->GetSurfaceBufferHeight());
482 externalTextureInfo.SetIsMipMapped(false);
483 externalTextureInfo.SetTarget(GL_TEXTURE_EXTERNAL_OES);
484 externalTextureInfo.SetID(eglTextureId);
485 auto glType = GR_GL_RGBA8;
486 auto pixelFmt = param.buffer->GetFormat();
487 if (pixelFmt == GRAPHIC_PIXEL_FMT_BGRA_8888) {
488 glType = GR_GL_BGRA8;
489 } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_P010 || pixelFmt == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
490 glType = GL_RGB10_A2;
491 }
492 externalTextureInfo.SetFormat(glType);
493
494 std::shared_ptr<Drawing::Image> layerImage = std::make_shared<Drawing::Image>();
495 if (!layerImage->BuildFromTexture(*context, externalTextureInfo,
496 Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr)) {
497 RS_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromGL image BuildFromTexture failed");
498 return nullptr;
499 }
500
501 std::shared_ptr<Drawing::Image> cutDownImage = std::make_shared<Drawing::Image>();
502 cutDownImage->BuildSubset(layerImage, imgCutRect, *context);
503 Drawing::ImageInfo info = Drawing::ImageInfo(imgCutRect.GetWidth(), imgCutRect.GetHeight(),
504 Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL);
505
506 std::shared_ptr<Drawing::Surface> surface = Drawing::Surface::MakeRenderTarget(context.get(), false, info);
507 if (surface == nullptr) {
508 RS_LOGE("RSMagicPointerRenderManager::GetIntersectImageFromGL MakeRenderTarget failed.");
509 return nullptr;
510 }
511 auto drawCanvas = std::make_shared<RSPaintFilterCanvas>(surface.get());
512 drawCanvas->DrawImage(*cutDownImage, 0.f, 0.f, Drawing::SamplingOptions());
513 surface->FlushAndSubmit(true);
514 return surface.get()->GetImageSnapshot();
515 }
516 #endif
517 } // namespace Rosen
518 } // namespace OHOS