32 std::uint64_t windowBufferUsage = 0;
33 auto getUsageRes = ::OH_NativeWindow_NativeWindowHandleOpt(
34 nativeWindow, ::NativeWindowOperation::GET_USAGE, &windowBufferUsage);
35 if (Q_UNLIKELY(getUsageRes != ohNativeWindowErrorCodeSuccess))
36 qOhosReportFatalErrorAndAbort(
"QOhosNativeXComponent: error reading window buffer usage: %d", getUsageRes);
38 std::uint64_t requestedWindowBufferUsage = windowBufferUsage | usageSetBits;
39 if (requestedWindowBufferUsage != windowBufferUsage) {
40 auto setUsageRes = ::OH_NativeWindow_NativeWindowHandleOpt(
41 nativeWindow, ::NativeWindowOperation::SET_USAGE, requestedWindowBufferUsage);
42 if (Q_UNLIKELY(setUsageRes != ohNativeWindowErrorCodeSuccess))
43 qOhosReportFatalErrorAndAbort(
"QOhosNativeXComponent: error setting window buffer usage: %d", setUsageRes);
49 auto setFormatRes = ::OH_NativeWindow_NativeWindowHandleOpt(
50 nativeWindow, ::NativeWindowOperation::SET_FORMAT, QOhosSurface::bufferFormat);
51 if (Q_UNLIKELY(setFormatRes != ohNativeWindowErrorCodeSuccess)) {
52 qOhosReportFatalErrorAndAbort(
53 "%s: QOhosNativeXComponent: error setting window buffer format: %d",
54 Q_FUNC_INFO, setFormatRes);
71 void *bufferMemory = ::mmap(
72 bufferHandle->virAddr, bufferHandle->size, PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
75 int mmapErrno = errno;
76 qCWarning(QtForOhos,
"%s: mmap failed with error: %d", Q_FUNC_INFO, mmapErrno);
80 outMemory = bufferMemory;
86 std::array<::pollfd, 1> pollFileDescriptors = {{
95 pollRetCode = ::poll(pollFileDescriptors.data(), pollFileDescriptors.size(), timeoutMs.count());
96 }
while (pollRetCode == -1 && (errno == EINTR || errno == EAGAIN));
98 auto pollErrno = errno;
100 if (pollRetCode == -1) {
102 QtForOhos,
"%s: polling '%s' file descriptor failed with error: %d",
103 Q_FUNC_INFO, fdName, pollErrno);
104 }
else if (pollRetCode == 0) {
106 QtForOhos,
"%s: polling '%s' file descriptor timed out",
107 Q_FUNC_INFO, fdName);
110 return pollRetCode > 0;
116QOhosSurface::mapNativeBufferFormatToQImageFormatOrFail(
std::int32_t format)
119 Q_BYTE_ORDER == Q_LITTLE_ENDIAN,
120 "Pixel format mapping is currently supported for little-endian targets only");
122 QImage::Format result;
125 case ::NATIVEBUFFER_PIXEL_FMT_RGB_888:
126 result = QImage::Format_RGB888;
128 case ::NATIVEBUFFER_PIXEL_FMT_RGBA_8888:
129 result = QImage::Format_RGBA8888;
131 case ::NATIVEBUFFER_PIXEL_FMT_BGRA_8888:
132 result = QImage::Format_ARGB32_Premultiplied;
135 qOhosReportFatalErrorAndAbort(
"%s: unsupported format %d", Q_FUNC_INFO, format);
141QOhosOptional<QSize> QOhosSurface::tryGetBufferGeometryForWindow(::OHNativeWindow *nativeWindow)
143 std::int32_t surfaceWidth = 0;
144 std::int32_t surfaceHeight = 0;
148 std::int32_t getWindowHandleErrorCode = ::OH_NativeWindow_NativeWindowHandleOpt(
149 nativeWindow, ::GET_BUFFER_GEOMETRY, &surfaceHeight, &surfaceWidth);
151 return getWindowHandleErrorCode == ohNativeWindowErrorCodeSuccess
152 ? QOhosOptional<QSize>({surfaceWidth, surfaceHeight})
153 : makeEmptyQOhosOptional();
173 ::OHNativeWindow *nativeWindow,
const QOhosOptional<QSize> &optSurfaceSize)
175 if (nativeWindow ==
nullptr)
176 qOhosReportFatalErrorAndAbort(
"NativeWindow cannot be null");
178 m_nativeWindow = nativeWindow;
182 m_vulkanSurface->setNativeWindowSurface(nativeWindow);
184 setupNativeWindowBufferUsage(
186 ::OH_NativeBuffer_Usage::NATIVEBUFFER_USAGE_CPU_READ);
189 m_eglSurface->setNativeWindowSurface(
190 reinterpret_cast<::EGLNativeWindowType>(m_nativeWindow), optSurfaceSize);
194EGLSurface QOhosSurface::tryGetOrCreateEGLWindowSurface(EGLDisplay display, EGLConfig config,
bool swappingBuffers)
197 m_eglSurface = std::make_unique<QOhosEGLSurface>();
198 m_eglSurface->setNativeWindowSurface(
199 reinterpret_cast<::EGLNativeWindowType>(m_nativeWindow), makeEmptyQOhosOptional());
201 return m_eglSurface->tryGetOrCreateEGLWindowSurface(display, config, swappingBuffers, {});
210 std::function<std::vector<::Region::Rect>(QImage &, ::BufferHandle *)> paintFunc,
211 std::function<
void(::BufferHandle *)> onFlushSuccessFunc)
213 ::OHNativeWindowBuffer *nativeWindowBuffer =
nullptr;
214 auto fenceFileDescriptor = makeFdAutoClosingWrapper();
216 setupNativeWindowBufferFormat(m_nativeWindow);
218 auto requestBufferEc = ::OH_NativeWindow_NativeWindowRequestBuffer(
219 m_nativeWindow, &nativeWindowBuffer, fenceFileDescriptor.get());
220 if (requestBufferEc != ohNativeWindowErrorCodeSuccess) {
221 qCWarning(QtForOhos,
"%s: NativeWindowRequestBuffer failed with error code: %d", Q_FUNC_INFO, requestBufferEc);
225 auto nativeWindowAbortBufferGuard = qScopeGuard([nativeWindow = m_nativeWindow, nativeWindowBuffer](){
226 auto abortBufferEc = ::OH_NativeWindow_NativeWindowAbortBuffer(nativeWindow, nativeWindowBuffer);
227 if (abortBufferEc != ohNativeWindowErrorCodeSuccess)
228 qCWarning(QtForOhos,
"%s: NativeWindowAbortBuffer failed with error code: %d", Q_FUNC_INFO, abortBufferEc);
231 ::BufferHandle *bufferHandle = ::OH_NativeWindow_GetBufferHandleFromNative(nativeWindowBuffer);
232 if (bufferHandle ==
nullptr) {
233 qCWarning(QtForOhos,
"%s: GetBufferHandleFromNative returned null", Q_FUNC_INFO);
237 QImage::Format dstImageFormat = QOhosSurface::mapNativeBufferFormatToQImageFormatOrFail(bufferHandle->format);
238 QSize dstImageSize{bufferHandle->width, bufferHandle->height};
240 void *bufferMemory =
nullptr;
241 if (!tryMapBufferHandleMemory(bufferHandle, bufferMemory))
244 auto unmapMemoryGuard = qScopeGuard([bufferMemory, bufferMemorySize = bufferHandle->size]() {
245 int result = ::munmap(bufferMemory, bufferMemorySize);
247 int munmapErrno = errno;
248 qCWarning(QtForOhos,
"%s: munmap failed with error: %d", Q_FUNC_INFO, munmapErrno);
252 if (*fenceFileDescriptor != -1) {
253 if (!waitForFdReadyForReadOrTimeout(*fenceFileDescriptor,
"window buffer fence", ch::seconds(3)))
258 reinterpret_cast<uchar *>(bufferMemory),
259 dstImageSize.width(), dstImageSize.height(),
260 bufferHandle->stride,
263 auto rects = paintFunc(dstImage, bufferHandle);
265 const std::int32_t acquireFenceFileDescriptor = -1;
266 auto flushBufferEc = ::OH_NativeWindow_NativeWindowFlushBuffer(
267 m_nativeWindow, nativeWindowBuffer, acquireFenceFileDescriptor,
269 .rects = rects.empty() ?
nullptr : rects.data(),
270 .rectNumber =
static_cast<std::int32_t>(rects.size()),
272 if (flushBufferEc != ohNativeWindowErrorCodeSuccess) {
273 qCWarning(QtForOhos,
"%s: failed to flush buffer with error code: %d", Q_FUNC_INFO, flushBufferEc);
276 onFlushSuccessFunc(bufferHandle);
277 nativeWindowAbortBufferGuard.dismiss();