HarmonyOS 鸿蒙Next:Native里连续的像素刷新应该怎么做

HarmonyOS 鸿蒙Next:Native里连续的像素刷新应该怎么做

目前遇到问题,使用XComponent连续对同一区域buffer刷新,第一帧渲染正常的情况下,第二帧渲染前,一定会黑屏一下。imagePixel 一直是同一个,外部会有一次像素copy。不知道问题出在哪里? 即使连续的将 imagePixel 全部设置为全红色,一样会有黑屏问题

void PluginRender::RefreshBitmap(std::string &id, gpointer imagePixel, gint x, gint y, gint width, gint height) {
    PluginRender *render = PluginRender::GetInstance(id);
    if (render == nullptr) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0, PluginRenderTag, "RefreshBitmap render = null");
        return;
    }
    // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
    OHNativeWindowBuffer *buffer = nullptr;
    int releaseFenceFd = -1;
    int32_t ret = OH_NativeWindow_NativeWindowRequestBuffer(render->nativeWindow_, &buffer, &releaseFenceFd);
    if (ret != 0 || buffer == nullptr) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0, PluginRenderTag, "RefreshBitmap failed, ret != 0");
        return;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0, PluginRenderTag, "RefreshBitmap OH_NativeWindow_NativeWindowRequestBuffer, fenceFd = %{public}d", releaseFenceFd);
    BufferHandle *bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
    uint32_t *mappedAddr = static_cast<uint32_t *>(
        // 使用内存映射函数mmap将bufferHandle对应的共享内存映射到用户空间,可以通过映射出来的虚拟地址向bufferHandle中写入图像数据
        // bufferHandle->virAddr是bufferHandle在共享内存中的起始地址,bufferHandle->size是bufferHandle在共享内存中的内存占用大小
        mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0));
    if (mappedAddr == MAP_FAILED) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0, PluginRenderTag, "RefreshBitmap mmap failed");
        return;
    }

    int retCode = -1;
    uint32_t timeout = 3000;
    if (releaseFenceFd != -1) {
        struct pollfd pollfds = {0};
        pollfds.fd = releaseFenceFd;
        pollfds.events = POLLIN;
        do {
            retCode = poll(&pollfds, 1, timeout);
        } while (retCode == -1 && (errno == EINTR || errno == EAGAIN));
        close(releaseFenceFd); // 防止fd泄漏
    }

    // 画完后获取像素地址,地址指向的内存包含画布画的像素数据
    uint32_t *value = static_cast<uint32_t *>(imagePixel);

    // 使用mmap获取到的地址来访问内存
    uint32_t *pixel = static_cast<uint32_t *>(mappedAddr);
    for (uint32_t x = 0; x < width; x++) {
        for (uint32_t y = 0; y < height; y++) {
            *pixel++ = *value++;
        }
    }

    // 如果Region中的Rect为nullptr,或者rectNumber为0,则认为OHNativeWindowBuffer全部有内容更改。
    Region region;
    region.rectNumber = 1;
    region.rects = new Region::Rect[1]{{x, y, static_cast<uint32_t>(width), static_cast<uint32_t>(height)}};

    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0, PluginRenderTag, "RefreshBitmap OH_NativeWindow_NativeWindowFlushBuffer before, x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d", region.rects[0].x,
                 region.rects[0].y, region.rects[0].w, region.rects[0].h);
    int acquireFenceFd = -1;
    // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
    int32_t flushBufferRet = OH_NativeWindow_NativeWindowFlushBuffer(render->nativeWindow_, buffer, acquireFenceFd, region);
    // 内存使用完记得去掉内存映射
    int munmapRet = munmap(mappedAddr, bufferHandle->size);
    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0, PluginRenderTag, "RefreshBitmap OH_NativeWindow_NativeWindowFlushBuffer, flushBufferRet = %{public}d, munmapRet = %{public}d,", flushBufferRet, munmapRet);
}


更多关于HarmonyOS 鸿蒙Next:Native里连续的像素刷新应该怎么做的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复
do_color_convert(displayData, x, y, width, height);
std::string id = "xcomponentId";
PluginRender::RefreshBitmap(id, displayData->imageBitmap, x, y, width, height);

uint32_t Convert32xRGBToRGBA8888(uint32_t rgb) {
//     uint8_t r = (rgb >> 16) & 0xFF; // 提取红色
//     uint8_t g = (rgb >> 8) & 0xFF;  // 提取绿色
//     uint8_t b = rgb & 0xFF;         // 提取蓝色
//     uint8_t a = 255;                // 设置 alpha 为 255

    uint8_t r = 255;
    uint8_t g = 0;
    uint8_t b = 0;
    uint8_t a = 255; // 设置 alpha 为 255

    return (a << 24) | (r << 16) | (g << 8) | b; // 返回 RGBA 8888 格式
}

static void do_color_convert(SpiceDisplayData *displayData, gint x, gint y, gint w, gint h) {
    OH_LOG_Print(LOG_APP, LOG_DEBUG, GLOBAL_RESMGR, tag, "do_color_convert, format: %{public}d, stride: %{public}d", displayData->imageFormat, displayData->stride);
    int i, j, maxy, maxx, miny, minx;
    guint32 *dest = (guint32 *)displayData->imageBitmap;
    guint32 *src = (guint32 *)displayData->origin_imgdata;

    miny = MAX(y, 0);
    minx = MAX(x, 0);
    maxy = MIN(y + h, displayData->height);
    maxx = MIN(x + w, displayData->width);

    dest += (displayData->stride / 4) * miny; // 计算目标行的起始地址
    src += (displayData->stride / 2) * miny;  // 计算源行的起始地址

    for (j = miny; j < maxy; j++) {
        for (i = minx; i < maxx; i++) {
            dest[i] = Convert32xRGBToRGBA8888(src[i]);
        }
        dest += displayData->stride / 4; // 移动到下一行
        src += displayData->stride / 2;  // 移动到下一行
    }
}

更多关于HarmonyOS 鸿蒙Next:Native里连续的像素刷新应该怎么做的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,Native层实现连续的像素刷新通常涉及对图形界面的高效更新。以下是一些关键步骤和考虑因素:

  1. 使用高效的图形API:利用HarmonyOS提供的图形API(如Canvas、Surface等)进行像素绘制和更新。确保在绘制过程中尽量减少不必要的计算和渲染开销。
  2. 双缓冲技术:采用双缓冲机制,在后台缓冲区中绘制新帧,然后一次性将其切换到前台显示,以减少闪烁和撕裂现象。
  3. 异步更新:将像素更新操作放在异步线程中执行,避免阻塞主线程,确保界面流畅。
  4. 优化刷新策略:根据实际需求设计合理的刷新策略,如按需刷新、定时刷新或基于事件触发的刷新。
  5. 资源管理:合理管理图形资源,如内存、纹理等,避免资源泄漏和过度消耗。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部