@@ -10,25 +10,42 @@ use euclid::default::Size2D;
10
10
use log:: info;
11
11
12
12
use crate :: egl;
13
- use crate :: egl:: types:: EGLSurface ;
13
+ use crate :: egl:: types:: { EGLSurface , EGLint } ;
14
14
use crate :: gl;
15
15
use crate :: gl:: types:: { GLenum , GLuint } ;
16
+ use crate :: gl_utils;
17
+ use crate :: platform:: egl:: ohos_ffi:: { eglGetNativeClientBufferANDROID, EGL_NATIVE_BUFFER_OHOS } ;
18
+ use crate :: platform:: generic;
16
19
use crate :: platform:: generic:: egl:: device:: EGL_FUNCTIONS ;
20
+ use crate :: platform:: generic:: egl:: ffi:: EGLImageKHR ;
17
21
use crate :: platform:: generic:: egl:: ffi:: EGL_EXTENSION_FUNCTIONS ;
22
+ use crate :: platform:: generic:: egl:: ffi:: EGL_IMAGE_PRESERVED_KHR ;
18
23
use crate :: platform:: generic:: egl:: ffi:: EGL_NO_IMAGE_KHR ;
24
+ use crate :: renderbuffers:: Renderbuffers ;
19
25
use crate :: { Error , SurfaceAccess , SurfaceID , SurfaceInfo , SurfaceType } ;
20
26
21
27
use super :: super :: context:: { Context , GL_FUNCTIONS } ;
22
28
use super :: super :: device:: Device ;
23
29
use super :: super :: ohos_ffi:: {
24
- NativeWindowOperation , OHNativeWindow , OH_NativeWindow_NativeWindowHandleOpt ,
30
+ NativeWindowOperation , OHNativeWindow , OH_NativeBuffer , OH_NativeBuffer_Alloc ,
31
+ OH_NativeBuffer_Config , OH_NativeBuffer_Format , OH_NativeBuffer_Unreference ,
32
+ OH_NativeBuffer_Usage , OH_NativeWindow_NativeWindowHandleOpt ,
25
33
} ;
26
34
use super :: { Surface , SurfaceTexture } ;
27
35
28
36
const SURFACE_GL_TEXTURE_TARGET : GLenum = gl:: TEXTURE_2D ;
29
37
30
38
pub ( crate ) enum SurfaceObjects {
31
- Window { egl_surface : EGLSurface } ,
39
+ HardwareBuffer {
40
+ hardware_buffer : * mut OH_NativeBuffer ,
41
+ egl_image : EGLImageKHR ,
42
+ framebuffer_object : GLuint ,
43
+ texture_object : GLuint ,
44
+ renderbuffers : Renderbuffers ,
45
+ } ,
46
+ Window {
47
+ egl_surface : EGLSurface ,
48
+ } ,
32
49
}
33
50
34
51
/// An OHOS native window.
@@ -58,10 +75,65 @@ impl Device {
58
75
59
76
fn create_generic_surface (
60
77
& mut self ,
61
- _context : & Context ,
62
- _size : & Size2D < i32 > ,
78
+ context : & Context ,
79
+ size : & Size2D < i32 > ,
63
80
) -> Result < Surface , Error > {
64
- Err ( Error :: Unimplemented )
81
+ let _guard = self . temporarily_make_context_current ( context) ?;
82
+
83
+ let usage = OH_NativeBuffer_Usage :: HW_RENDER | OH_NativeBuffer_Usage :: HW_TEXTURE ;
84
+
85
+ let config = OH_NativeBuffer_Config {
86
+ width : size. width ,
87
+ height : size. height ,
88
+ format : OH_NativeBuffer_Format :: RGBA_8888 ,
89
+ usage : usage,
90
+ stride : 10 , // used same magic number as android. I have no idea
91
+ } ;
92
+
93
+ GL_FUNCTIONS . with ( |gl| {
94
+ unsafe {
95
+ let hardware_buffer = OH_NativeBuffer_Alloc ( & config as * const _ ) ;
96
+ assert ! ( !hardware_buffer. is_null( ) , "Failed to create native buffer" ) ;
97
+
98
+ // Create an EGL image, and bind it to a texture.
99
+ let egl_image = self . create_egl_image ( context, hardware_buffer) ;
100
+
101
+ // Initialize and bind the image to the texture.
102
+ let texture_object =
103
+ generic:: egl:: surface:: bind_egl_image_to_gl_texture ( gl, egl_image) ;
104
+
105
+ // Create the framebuffer, and bind the texture to it.
106
+ let framebuffer_object = gl_utils:: create_and_bind_framebuffer (
107
+ gl,
108
+ SURFACE_GL_TEXTURE_TARGET ,
109
+ texture_object,
110
+ ) ;
111
+
112
+ // Bind renderbuffers as appropriate.
113
+ let context_descriptor = self . context_descriptor ( context) ;
114
+ let context_attributes = self . context_descriptor_attributes ( & context_descriptor) ;
115
+ let renderbuffers = Renderbuffers :: new ( gl, size, & context_attributes) ;
116
+ renderbuffers. bind_to_current_framebuffer ( gl) ;
117
+
118
+ debug_assert_eq ! (
119
+ gl. CheckFramebufferStatus ( gl:: FRAMEBUFFER ) ,
120
+ gl:: FRAMEBUFFER_COMPLETE
121
+ ) ;
122
+
123
+ Ok ( Surface {
124
+ size : * size,
125
+ context_id : context. id ,
126
+ objects : SurfaceObjects :: HardwareBuffer {
127
+ hardware_buffer,
128
+ egl_image,
129
+ framebuffer_object,
130
+ texture_object,
131
+ renderbuffers,
132
+ } ,
133
+ destroyed : false ,
134
+ } )
135
+ }
136
+ } )
65
137
}
66
138
67
139
unsafe fn create_window_surface (
@@ -110,14 +182,34 @@ impl Device {
110
182
/// in another context.
111
183
///
112
184
/// Calling this method on a widget surface returns a `WidgetAttached` error.
113
- /// On OpenHarmony, currently only widget surfaces are implemented in surfman, so
114
- /// this method unconditionally returns the `WidgetAttached` error.
115
185
pub fn create_surface_texture (
116
186
& self ,
117
- _context : & mut Context ,
187
+ context : & mut Context ,
118
188
surface : Surface ,
119
189
) -> Result < SurfaceTexture , ( Error , Surface ) > {
120
- Err ( ( Error :: WidgetAttached , surface) )
190
+ unsafe {
191
+ match surface. objects {
192
+ SurfaceObjects :: Window { .. } => return Err ( ( Error :: WidgetAttached , surface) ) ,
193
+ SurfaceObjects :: HardwareBuffer {
194
+ hardware_buffer, ..
195
+ } => GL_FUNCTIONS . with ( |gl| {
196
+ let _guard = match self . temporarily_make_context_current ( context) {
197
+ Ok ( guard) => guard,
198
+ Err ( err) => return Err ( ( err, surface) ) ,
199
+ } ;
200
+
201
+ let local_egl_image = self . create_egl_image ( context, hardware_buffer) ;
202
+ let texture_object =
203
+ generic:: egl:: surface:: bind_egl_image_to_gl_texture ( gl, local_egl_image) ;
204
+ Ok ( SurfaceTexture {
205
+ surface,
206
+ local_egl_image,
207
+ texture_object,
208
+ phantom : PhantomData ,
209
+ } )
210
+ } ) ,
211
+ }
212
+ }
121
213
}
122
214
123
215
/// Displays the contents of a widget surface on screen.
@@ -138,6 +230,7 @@ impl Device {
138
230
egl. SwapBuffers ( self . egl_display , egl_surface) ;
139
231
Ok ( ( ) )
140
232
}
233
+ SurfaceObjects :: HardwareBuffer { .. } => Err ( Error :: NoWidgetAttached ) ,
141
234
}
142
235
} )
143
236
}
@@ -153,6 +246,34 @@ impl Device {
153
246
Ok ( ( ) )
154
247
}
155
248
249
+ #[ allow( non_snake_case) ]
250
+ unsafe fn create_egl_image (
251
+ & self ,
252
+ _: & Context ,
253
+ hardware_buffer : * mut OH_NativeBuffer ,
254
+ ) -> EGLImageKHR {
255
+ let client_buffer = eglGetNativeClientBufferANDROID ( hardware_buffer as * const _ ) ;
256
+ assert ! ( !client_buffer. is_null( ) ) ;
257
+
258
+ // Create the EGL image.
259
+ let egl_image_attributes = [
260
+ EGL_IMAGE_PRESERVED_KHR as EGLint ,
261
+ egl:: TRUE as EGLint ,
262
+ egl:: NONE as EGLint ,
263
+ 0 ,
264
+ ] ;
265
+ let egl_image = ( EGL_EXTENSION_FUNCTIONS . CreateImageKHR ) (
266
+ self . egl_display ,
267
+ egl:: NO_CONTEXT ,
268
+ EGL_NATIVE_BUFFER_OHOS ,
269
+ client_buffer. cast_mut ( ) . cast ( ) ,
270
+ egl_image_attributes. as_ptr ( ) ,
271
+ ) ;
272
+ assert_ne ! ( egl_image, EGL_NO_IMAGE_KHR ) ;
273
+ info ! ( "surfman created an EGL image succesfully!" ) ;
274
+ egl_image
275
+ }
276
+
156
277
/// Destroys a surface.
157
278
///
158
279
/// The supplied context must be the context the surface is associated with, or this returns
@@ -171,6 +292,34 @@ impl Device {
171
292
172
293
unsafe {
173
294
match surface. objects {
295
+ SurfaceObjects :: HardwareBuffer {
296
+ ref mut hardware_buffer,
297
+ ref mut egl_image,
298
+ ref mut framebuffer_object,
299
+ ref mut texture_object,
300
+ ref mut renderbuffers,
301
+ } => {
302
+ GL_FUNCTIONS . with ( |gl| {
303
+ gl. BindFramebuffer ( gl:: FRAMEBUFFER , 0 ) ;
304
+ gl. DeleteFramebuffers ( 1 , framebuffer_object) ;
305
+ * framebuffer_object = 0 ;
306
+
307
+ renderbuffers. destroy ( gl) ;
308
+
309
+ gl. DeleteTextures ( 1 , texture_object) ;
310
+ * texture_object = 0 ;
311
+
312
+ let egl_display = self . egl_display ;
313
+ let result =
314
+ ( EGL_EXTENSION_FUNCTIONS . DestroyImageKHR ) ( egl_display, * egl_image) ;
315
+ assert_ne ! ( result, egl:: FALSE ) ;
316
+ * egl_image = EGL_NO_IMAGE_KHR ;
317
+
318
+ let res = OH_NativeBuffer_Unreference ( * hardware_buffer) ;
319
+ assert_eq ! ( res, 0 , "OH_NativeBuffer_Unreference failed" ) ;
320
+ * hardware_buffer = ptr:: null_mut ( ) ;
321
+ } ) ;
322
+ }
174
323
SurfaceObjects :: Window {
175
324
ref mut egl_surface,
176
325
} => EGL_FUNCTIONS . with ( |egl| {
@@ -242,6 +391,9 @@ impl Device {
242
391
id : surface. id ( ) ,
243
392
context_id : surface. context_id ,
244
393
framebuffer_object : match surface. objects {
394
+ SurfaceObjects :: HardwareBuffer {
395
+ framebuffer_object, ..
396
+ } => framebuffer_object,
245
397
SurfaceObjects :: Window { .. } => 0 ,
246
398
} ,
247
399
}
@@ -267,6 +419,7 @@ impl NativeWidget {
267
419
impl Surface {
268
420
pub ( super ) fn id ( & self ) -> SurfaceID {
269
421
match self . objects {
422
+ SurfaceObjects :: HardwareBuffer { egl_image, .. } => SurfaceID ( egl_image as usize ) ,
270
423
SurfaceObjects :: Window { egl_surface } => SurfaceID ( egl_surface as usize ) ,
271
424
}
272
425
}
0 commit comments