FreeRDP
Loading...
Searching...
No Matches
video.c
1
20#include "../core/update.h"
21
22#include <winpr/assert.h>
23
24#include <freerdp/client/geometry.h>
25#include <freerdp/client/video.h>
26#include <freerdp/gdi/gdi.h>
27#include <freerdp/gdi/video.h>
28#include <freerdp/gdi/region.h>
29
30void gdi_video_geometry_init(rdpGdi* gdi, GeometryClientContext* geom)
31{
32 WINPR_ASSERT(gdi);
33 WINPR_ASSERT(geom);
34
35 gdi->geometry = geom;
36
37 if (gdi->video)
38 {
39 VideoClientContext* video = gdi->video;
40
41 WINPR_ASSERT(video);
42 WINPR_ASSERT(video->setGeometry);
43 video->setGeometry(video, gdi->geometry);
44 }
45}
46
47void gdi_video_geometry_uninit(rdpGdi* gdi, GeometryClientContext* geom)
48{
49 WINPR_ASSERT(gdi);
50 WINPR_ASSERT(geom);
51 WINPR_UNUSED(gdi);
52 WINPR_UNUSED(geom);
53}
54
55static VideoSurface* gdiVideoCreateSurface(WINPR_ATTR_UNUSED VideoClientContext* video, UINT32 x,
56 UINT32 y, UINT32 width, UINT32 height)
57{
58 return VideoClient_CreateCommonContext(sizeof(VideoSurface), x, y, width, height);
59}
60
61static BOOL gdiVideoShowSurface(VideoClientContext* video, const VideoSurface* surface,
62 UINT32 destinationWidth, UINT32 destinationHeight)
63{
64 BOOL rc = FALSE;
65 rdpGdi* gdi = nullptr;
66 rdpUpdate* update = nullptr;
67
68 WINPR_ASSERT(video);
69 WINPR_ASSERT(surface);
70
71 gdi = (rdpGdi*)video->custom;
72 WINPR_ASSERT(gdi);
73 WINPR_ASSERT(gdi->context);
74
75 update = gdi->context->update;
76 WINPR_ASSERT(update);
77
78 if (!update_begin_paint(update))
79 goto fail;
80
81 if ((gdi->width < 0) || (gdi->height < 0))
82 goto fail;
83
84 {
85 const UINT32 nXSrc = surface->x;
86 const UINT32 nYSrc = surface->y;
87 const UINT32 nXDst = nXSrc;
88 const UINT32 nYDst = nYSrc;
89 const UINT32 width = (destinationWidth + surface->x < (UINT32)gdi->width)
90 ? destinationWidth
91 : (UINT32)gdi->width - surface->x;
92 const UINT32 height = (destinationHeight + surface->y < (UINT32)gdi->height)
93 ? destinationHeight
94 : (UINT32)gdi->height - surface->y;
95
96 WINPR_ASSERT(gdi->primary_buffer);
97 WINPR_ASSERT(gdi->primary);
98 WINPR_ASSERT(gdi->primary->hdc);
99
100 if (!freerdp_image_scale(gdi->primary_buffer, gdi->primary->hdc->format, gdi->stride, nXDst,
101 nYDst, width, height, surface->data, surface->format,
102 surface->scanline, 0, 0, surface->w, surface->h))
103 goto fail;
104
105 if ((nXDst > INT32_MAX) || (nYDst > INT32_MAX) || (width > INT32_MAX) ||
106 (height > INT32_MAX))
107 goto fail;
108
109 rc = gdi_InvalidateRegion(gdi->primary->hdc, (INT32)nXDst, (INT32)nYDst, (INT32)width,
110 (INT32)height);
111 }
112fail:
113
114 if (!update_end_paint(update))
115 return FALSE;
116
117 return rc;
118}
119
120static BOOL gdiVideoDeleteSurface(VideoClientContext* video, VideoSurface* surface)
121{
122 WINPR_UNUSED(video);
123 VideoClient_DestroyCommonContext(surface);
124 return TRUE;
125}
126
127void gdi_video_control_init(rdpGdi* gdi, VideoClientContext* video)
128{
129 WINPR_ASSERT(gdi);
130 WINPR_ASSERT(video);
131
132 gdi->video = video;
133 video->custom = gdi;
134 video->createSurface = gdiVideoCreateSurface;
135 video->showSurface = gdiVideoShowSurface;
136 video->deleteSurface = gdiVideoDeleteSurface;
137 video->setGeometry(video, gdi->geometry);
138}
139
140void gdi_video_control_uninit(rdpGdi* gdi, WINPR_ATTR_UNUSED VideoClientContext* video)
141{
142 WINPR_ASSERT(gdi);
143 gdi->video = nullptr;
144}
145
146void gdi_video_data_init(WINPR_ATTR_UNUSED rdpGdi* gdi, WINPR_ATTR_UNUSED VideoClientContext* video)
147{
148 WINPR_ASSERT(gdi);
149 WINPR_ASSERT(gdi->context);
150}
151
152void gdi_video_data_uninit(WINPR_ATTR_UNUSED rdpGdi* gdi,
153 WINPR_ATTR_UNUSED VideoClientContext* context)
154{
155 WINPR_ASSERT(gdi);
156 WINPR_ASSERT(gdi->context);
157}
158
159VideoSurface* VideoClient_CreateCommonContext(size_t size, UINT32 x, UINT32 y, UINT32 w, UINT32 h)
160{
161 VideoSurface* ret = nullptr;
162
163 WINPR_ASSERT(size >= sizeof(VideoSurface));
164
165 ret = calloc(1, size);
166 if (!ret)
167 return nullptr;
168
169 ret->format = PIXEL_FORMAT_BGRX32;
170 ret->x = x;
171 ret->y = y;
172 ret->w = w;
173 ret->h = h;
174 ret->alignedWidth = ret->w + 32 - ret->w % 16;
175 ret->alignedHeight = ret->h + 32 - ret->h % 16;
176
177 ret->scanline = ret->alignedWidth * FreeRDPGetBytesPerPixel(ret->format);
178 ret->data = winpr_aligned_malloc(1ull * ret->scanline * ret->alignedHeight, 64);
179 if (!ret->data)
180 goto fail;
181 return ret;
182fail:
183 VideoClient_DestroyCommonContext(ret);
184 return nullptr;
185}
186
187void VideoClient_DestroyCommonContext(VideoSurface* surface)
188{
189 if (!surface)
190 return;
191 winpr_aligned_free(surface->data);
192 free(surface);
193}
an implementation of surface used by the video channel