Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2020
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 :
27 :
28 : #include "visual_manager.h"
29 : #include "texturing.h"
30 : #include "nodes_stacks.h"
31 : #include <gpac/options.h>
32 :
33 : #ifndef GPAC_DISABLE_3D
34 :
35 : #ifdef GPAC_USE_TINYGL
36 : #include <GL/oscontext.h>
37 : #endif
38 :
39 126 : GF_Err compositor_3d_set_aspect_ratio(GF_Compositor *compositor)
40 : {
41 : GF_Event evt;
42 : Double ratio;
43 : Fixed scaleX, scaleY;
44 :
45 126 : if (!compositor->display_height || !compositor->display_width) return GF_OK;
46 :
47 126 : compositor->visual->camera.flags |= CAM_IS_DIRTY;
48 :
49 126 : compositor->output_width = compositor->vp_width = compositor->display_width;
50 126 : compositor->output_height = compositor->vp_height = compositor->display_height;
51 126 : compositor->vp_x = 0;
52 126 : compositor->vp_y = 0;
53 :
54 : scaleX = scaleY = FIX_ONE;
55 126 : if (!compositor->has_size_info || compositor->inherit_type_3d) {
56 23 : compositor->visual->width = compositor->vp_width;
57 23 : compositor->visual->height = compositor->vp_height;
58 : } else {
59 103 : switch (compositor->aspect_ratio) {
60 : case GF_ASPECT_RATIO_FILL_SCREEN:
61 : break;
62 0 : case GF_ASPECT_RATIO_16_9:
63 0 : compositor->vp_height = 9 * compositor->vp_width / 16;
64 0 : break;
65 0 : case GF_ASPECT_RATIO_4_3:
66 0 : compositor->vp_height = 3 * compositor->vp_width / 4;
67 0 : break;
68 103 : default:
69 103 : ratio = compositor->scene_height;
70 103 : ratio /= compositor->scene_width;
71 103 : if (compositor->vp_width * ratio > compositor->vp_height) {
72 0 : compositor->vp_width = compositor->vp_height * compositor->scene_width;
73 0 : compositor->vp_width /= compositor->scene_height;
74 : }
75 : else {
76 103 : compositor->vp_height = compositor->vp_width * compositor->scene_height;
77 103 : compositor->vp_height /= compositor->scene_width;
78 : }
79 : break;
80 : }
81 103 : compositor->vp_x = (compositor->display_width - compositor->vp_width) / 2;
82 103 : compositor->vp_y = (compositor->display_height - compositor->vp_height) / 2;
83 : /*update size info for main visual*/
84 103 : if (compositor->visual) {
85 103 : compositor->visual->width = compositor->scene_width;
86 103 : compositor->visual->height = compositor->scene_height;
87 : }
88 : /*scaling is still needed for bitmap*/
89 103 : scaleX = gf_divfix(INT2FIX(compositor->vp_width), INT2FIX(compositor->scene_width));
90 103 : scaleY = gf_divfix(INT2FIX(compositor->vp_height), INT2FIX(compositor->scene_height));
91 : }
92 :
93 126 : if (compositor->has_size_info) {
94 103 : compositor->traverse_state->vp_size.x = INT2FIX(compositor->scene_width);
95 103 : compositor->traverse_state->vp_size.y = INT2FIX(compositor->scene_height);
96 : } else {
97 23 : compositor->traverse_state->vp_size.x = INT2FIX(compositor->output_width);
98 23 : compositor->traverse_state->vp_size.y = INT2FIX(compositor->output_height);
99 : }
100 126 : compositor_set_ar_scale(compositor, scaleX, scaleY);
101 :
102 :
103 : /*and resetup OpenGL*/
104 126 : evt.type = GF_EVENT_VIDEO_SETUP;
105 126 : evt.setup.width = compositor->display_width;
106 126 : evt.setup.height = compositor->display_height;
107 126 : evt.setup.back_buffer = GF_TRUE;
108 126 : evt.setup.disable_vsync = compositor->bench_mode ? GF_TRUE : GF_FALSE;
109 : #ifdef GPAC_USE_TINYGL
110 : evt.setup.use_opengl = GF_FALSE;
111 : #else
112 126 : evt.setup.use_opengl = GF_TRUE;
113 126 : compositor->is_opengl = GF_TRUE;
114 : #endif
115 :
116 126 : if (compositor->video_out->ProcessEvent(compositor->video_out, &evt)<0) {
117 0 : gf_sc_reset_graphics(compositor);
118 0 : return GF_OK;
119 : }
120 126 : if (evt.setup.use_opengl) {
121 125 : gf_opengl_init();
122 : }
123 :
124 : #if defined(GPAC_USE_TINYGL)
125 : {
126 : u32 bpp;
127 : GF_VideoSurface bb;
128 : GF_Err e = compositor->video_out->LockBackBuffer(compositor->video_out, &bb, 1);
129 : if (e==GF_OK) {
130 : switch (bb.pixel_format) {
131 : case GF_PIXEL_RGBX:
132 : case GF_PIXEL_ARGB:
133 : bpp = 32;
134 : break;
135 : case GF_PIXEL_RGB:
136 : case GF_PIXEL_BGR:
137 : bpp = 24;
138 : break;
139 : case GF_PIXEL_RGB_565:
140 : case GF_PIXEL_RGB_555:
141 : bpp = 16;
142 : break;
143 : default:
144 : e = GF_NOT_SUPPORTED;
145 : bpp = 0;
146 : break;
147 : }
148 : if (e==GF_OK) {
149 : compositor->tgl_ctx = ostgl_create_context(bb.width, bb.height, bpp, &bb.video_buffer, 1);
150 : if (compositor->tgl_ctx) ostgl_make_current(compositor->tgl_ctx, 0);
151 : }
152 : compositor->video_out->LockBackBuffer(compositor->video_out, &bb, 0);
153 : }
154 : }
155 : #endif
156 :
157 : return GF_OK;
158 : }
159 :
160 :
161 19 : GF_Camera *compositor_3d_get_camera(GF_Compositor *compositor)
162 : {
163 : #ifndef GPAC_DISABLE_VRML
164 21 : if (compositor->active_layer) {
165 0 : return compositor_layer3d_get_camera(compositor->active_layer);
166 : }
167 : #endif
168 21 : if (compositor->visual->type_3d)
169 20 : return &compositor->visual->camera;
170 : return NULL;
171 : }
172 :
173 2 : void compositor_3d_reset_camera(GF_Compositor *compositor)
174 : {
175 : GF_Camera *cam = compositor_3d_get_camera(compositor);
176 1 : if (cam) {
177 1 : camera_reset_viewpoint(cam, GF_TRUE);
178 1 : gf_sc_invalidate(compositor, NULL);
179 : }
180 2 : if (compositor->active_layer) gf_node_dirty_set(compositor->active_layer, 0, GF_TRUE);
181 2 : }
182 :
183 771 : void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
184 : {
185 : u8 alpha;
186 : GF_TextureHandler *txh;
187 771 : GF_Compositor *compositor = tr_state->visual->compositor;
188 :
189 771 : if (!asp->fill_texture)
190 : return;
191 : txh = asp->fill_texture;
192 635 : if (!txh || !txh->tx_io || !txh->width || !txh->height)
193 : return;
194 :
195 619 : if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
196 0 : if (compositor->depth_gl_type) {
197 0 : if (txh->data && gf_sc_texture_convert(txh) )
198 0 : visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
199 : return;
200 : }
201 : }
202 :
203 619 : alpha = GF_COL_A(asp->fill_color);
204 : /*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
205 619 : if (!alpha) alpha = GF_COL_A(asp->line_color);
206 :
207 619 : visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, GF_FALSE);
208 619 : visual_3d_enable_antialias(tr_state->visual, GF_FALSE);
209 :
210 619 : visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
211 :
212 619 : if (alpha && (alpha != 0xFF)) {
213 142 : gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
214 477 : } else if (gf_sc_texture_is_transparent(txh)) {
215 3 : gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
216 : } else {
217 474 : visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, GF_FALSE);
218 : }
219 : /*ignore texture transform for bitmap*/
220 619 : tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
221 619 : if (tr_state->mesh_num_textures) {
222 : /*we must check the w & h passed are correct because of bitmap node initialization*/
223 619 : if (width && height) {
224 619 : if (!stack->mesh) {
225 : SFVec2f size;
226 17 : size.x = width;
227 17 : size.y = height;
228 :
229 17 : stack->mesh = new_mesh();
230 17 : mesh_new_rectangle(stack->mesh, size, NULL, GF_FALSE);
231 : }
232 : }
233 619 : if (stack->mesh) {
234 : #ifdef GF_SR_USE_DEPTH
235 619 : if (tr_state->depth_offset) {
236 : GF_Matrix mx;
237 : Fixed offset;
238 0 : Fixed disp_depth = (compositor->dispdepth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->dispdepth);
239 0 : if (disp_depth) {
240 : GF_Matrix bck_mx;
241 0 : if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
242 0 : gf_mx_init(mx);
243 : /*add recalibration by the scene*/
244 : offset = tr_state->depth_offset;
245 0 : if (tr_state->visual->depth_vp_range) {
246 0 : offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
247 : }
248 0 : gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );
249 :
250 0 : gf_mx_copy(bck_mx, tr_state->model_matrix);
251 0 : gf_mx_add_matrix(&tr_state->model_matrix, &mx);
252 0 : visual_3d_mesh_paint(tr_state, stack->mesh);
253 : gf_mx_copy(tr_state->model_matrix, bck_mx);
254 : } else {
255 0 : visual_3d_mesh_paint(tr_state, stack->mesh);
256 : }
257 : } else
258 : #endif
259 619 : visual_3d_mesh_paint(tr_state, stack->mesh);
260 : }
261 619 : gf_sc_texture_disable(txh);
262 619 : tr_state->mesh_num_textures = 0;
263 : }
264 : }
265 :
266 : #endif
267 :
|