• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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