HarmonyOS:NativeWindow 開發指導

HarmonyOS開發者社群發表於2023-12-12

場景介紹

NativeWindow 是 HarmonyOS 本地平臺化視窗,表示圖形佇列的生產者端。開發者可以透過 NativeWindow 介面進行申請和提交 Buffer,配置 Buffer 屬性資訊。

針對 NativeWindow,常見的開發場景如下:

●  透過 NativeWindow 提供的 Native API 介面申請圖形 Buffer,並將生產圖形內容寫入圖形 Buffer,最終提交 Buffer 到圖形佇列

●  在適配 EGL 層的 eglswapbuffer 介面時,進行申請和提交 Buffer

介面說明

HarmonyOS:NativeWindow 開發指導


詳細的介面說明請參考 native_window

開發步驟

以下步驟描述了在 HarmonyOS 中如何使用 NativeWindow 提供的 Native API 介面,申請圖形 Buffer,並將生產圖形內容寫入圖形 Buffer 後,最終提交 Buffer 到圖形佇列。

新增動態連結庫

CMakeLists.txt 中新增以下 lib。


libace_ndk.z.so
libnative_window.so




標頭檔案



#
include 
<ace/xcomponent/native_interface_xcomponent.h>

#
include 
<native_window/external_window.h>


複製程式碼


1.  獲取 OHNativeWindow 例項

可在 OH_NativeXComponent_Callback 提供的介面中獲取 OHNativeWindow,下面提供一份程式碼示例。XComponent 模組的具體使用方法請參考 XComponent開發指導

a.  在 xxx.ets 中新增一個 XComponent 元件。


XComponent({ 
id: 
'xcomponentId'type: 
'surface', libraryname: 
'entry'})
    .width(
360)
    .height(
360)




b.  在 native c++ 層獲取 NativeXComponent。



napi_value 
exportInstance 
= nullptr;

// 用來解析出被wrap了NativeXComponent指標的屬性
napi_get_named_property(env, 
exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
OH_NativeXComponent *nativeXComponent = nullptr;

// 透過napi_unwrap介面,解析出NativeXComponent的例項指標
napi_unwrap(env, exportInstance, reinterpret_cast<
void**>(&nativeXComponent));

// 獲取XComponentId

char idStr[OH_XCOMPONENT_ID_LEN_MAX + 
1] = {};

uint64_t 
idSize 
= OH_XCOMPONENT_ID_LEN_MAX + 
1;
OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);




c.  定義 OH_NativeXComponent_Callback。



// 定義回撥函式

void 
OnSurfaceCreatedCB(OH_NativeXComponent* component, 
voidwindow)
{
    
// 可獲取 OHNativeWindow 例項
    
OHNativeWindow* nativeWindow = static_cast<
OHNativeWindow*>(
window);
    
// ...
}

void 
OnSurfaceChangedCB(OH_NativeXComponent* component, 
voidwindow)
{
    
// 可獲取 OHNativeWindow 例項
    
OHNativeWindow* nativeWindow = static_cast<
OHNativeWindow*>(
window);
    
// ...
}

void 
OnSurfaceDestroyedCB(OH_NativeXComponent* component, 
voidwindow)
{
    
// 可獲取 OHNativeWindow 例項
    
OHNativeWindow* nativeWindow = static_cast<
OHNativeWindow*>(
window);
    
// ...
}

void 
DispatchTouchEventCB(OH_NativeXComponent* component, 
voidwindow)
{
    
// 可獲取 OHNativeWindow 例項
    
OHNativeWindow* nativeWindow = static_cast<
OHNativeWindow*>(
window);
    
// ...
}






// 初始化 OH_NativeXComponent_Callback
OH_NativeXComponent_Callback callback;
callback.
OnSurfaceCreated = 
OnSurfaceCreatedCB;
callback.
OnSurfaceChanged = 
OnSurfaceChangedCB;
callback.
OnSurfaceDestroyed = 
OnSurfaceDestroyedCB;
callback.
DispatchTouchEvent = 
DispatchTouchEventCB;




d.  將 OH_NativeXComponent_Callback 註冊給 NativeXComponent。



// 註冊回撥函式

OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);




2.  設定 OHNativeWindowBuffer 的屬性。使用 OH_NativeWindow_NativeWindowHandleOpt 設定 OHNativeWindowBuffer 的屬性。



// 設定 OHNativeWindowBuffer 的寬高

int32_t 
code 
= SET_BUFFER_GEOMETRY;

int32_t 
width 
= 
0x100;

int32_t 
height 
= 
0x100;

// 這裡的nativeWindow是從上一步驟中的回撥函式中獲得的

int32_t 
ret 
= OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);




3.  從圖形佇列申請 OHNativeWindowBuffer


OHNativeWindowBuffer* buffer = 
nullptr;

int fenceFd;

// 透過 OH_NativeWindow_NativeWindowRequestBuffer 獲取 OHNativeWindowBuffer 例項

OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);

// 透過 OH_NativeWindow_GetBufferHandleFromNative 獲取 buffer 的 handle
BufferHandle* bufferHandle = 
OH_NativeWindow_GetBufferHandleFromNative(buffer);




4.  記憶體對映 mmap



#include <sys/mman.h>


// 使用系統介面mmap將bufferHandle對應的共享記憶體對映到使用者空間,可以透過對映出來的虛擬地址向bufferHandle中寫入影像資料 // bufferHandle->virAddr是bufferHandle在共享記憶體中的起始地址,bufferHandle->size是bufferHandle在共享記憶體中的記憶體佔用大小 void* mappedAddr = mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0); if (mappedAddr == MAP_FAILED) {     // mmap failed }



5.  將生產的內容寫入 OHNativeWindowBuffer



static 
uint32_t value = 
0x00;
value++;

uint32_t *pixel = 
static_cast<
uint32_t *>(mappedAddr); 
// 使用mmap獲取到的地址來訪問記憶體

for (
uint32_t x = 
0; x < width; x++) {
    
for (
uint32_t y = 
0;  y < height; y++) {
        *pixel++ = value;
    }
}




6.  提交 OHNativeWindowBuffer 到圖形佇列



// 設定重新整理區域,如果Region中的Rect為nullptr,或者rectNumber為0,則認為OHNativeWindowBuffer全部有內容更改。
Region region{
nullptr, 
0};

// 透過OH_NativeWindow_NativeWindowFlushBuffer 提交給消費者使用,例如:顯示在螢幕上。

OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);




7.  取消記憶體對映 munmap



// 記憶體使用完記得去掉記憶體對映

int result = munmap(mappedAddr, bufferHandle->size);

if (result == -
1) {
    
// munmap failed
}



來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70009402/viewspace-2999776/,如需轉載,請註明出處,否則將追究法律責任。

相關文章