Coverage Report

Created: 2026-02-26 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/gdi/video.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Video Optimized Remoting Virtual Channel Extension for X11
4
 *
5
 * Copyright 2017 David Fort <contact@hardening-consulting.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
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
30
void gdi_video_geometry_init(rdpGdi* gdi, GeometryClientContext* geom)
31
0
{
32
0
  WINPR_ASSERT(gdi);
33
0
  WINPR_ASSERT(geom);
34
35
0
  gdi->geometry = geom;
36
37
0
  if (gdi->video)
38
0
  {
39
0
    VideoClientContext* video = gdi->video;
40
41
0
    WINPR_ASSERT(video);
42
0
    WINPR_ASSERT(video->setGeometry);
43
0
    video->setGeometry(video, gdi->geometry);
44
0
  }
45
0
}
46
47
void gdi_video_geometry_uninit(rdpGdi* gdi, GeometryClientContext* geom)
48
0
{
49
0
  WINPR_ASSERT(gdi);
50
0
  WINPR_ASSERT(geom);
51
0
  WINPR_UNUSED(gdi);
52
0
  WINPR_UNUSED(geom);
53
0
}
54
55
static VideoSurface* gdiVideoCreateSurface(WINPR_ATTR_UNUSED VideoClientContext* video, UINT32 x,
56
                                           UINT32 y, UINT32 width, UINT32 height)
57
0
{
58
0
  return VideoClient_CreateCommonContext(sizeof(VideoSurface), x, y, width, height);
59
0
}
60
61
static BOOL gdiVideoShowSurface(VideoClientContext* video, const VideoSurface* surface,
62
                                UINT32 destinationWidth, UINT32 destinationHeight)
63
0
{
64
0
  BOOL rc = FALSE;
65
0
  rdpGdi* gdi = NULL;
66
0
  rdpUpdate* update = NULL;
67
68
0
  WINPR_ASSERT(video);
69
0
  WINPR_ASSERT(surface);
70
71
0
  gdi = (rdpGdi*)video->custom;
72
0
  WINPR_ASSERT(gdi);
73
0
  WINPR_ASSERT(gdi->context);
74
75
0
  update = gdi->context->update;
76
0
  WINPR_ASSERT(update);
77
78
0
  if (!update_begin_paint(update))
79
0
    goto fail;
80
81
0
  if ((gdi->width < 0) || (gdi->height < 0))
82
0
    goto fail;
83
84
0
  {
85
0
    const UINT32 nXSrc = surface->x;
86
0
    const UINT32 nYSrc = surface->y;
87
0
    const UINT32 nXDst = nXSrc;
88
0
    const UINT32 nYDst = nYSrc;
89
0
    const UINT32 width = (destinationWidth + surface->x < (UINT32)gdi->width)
90
0
                             ? destinationWidth
91
0
                             : (UINT32)gdi->width - surface->x;
92
0
    const UINT32 height = (destinationHeight + surface->y < (UINT32)gdi->height)
93
0
                              ? destinationHeight
94
0
                              : (UINT32)gdi->height - surface->y;
95
96
0
    WINPR_ASSERT(gdi->primary_buffer);
97
0
    WINPR_ASSERT(gdi->primary);
98
0
    WINPR_ASSERT(gdi->primary->hdc);
99
100
0
    if (!freerdp_image_scale(gdi->primary_buffer, gdi->primary->hdc->format, gdi->stride, nXDst,
101
0
                             nYDst, width, height, surface->data, surface->format,
102
0
                             surface->scanline, 0, 0, surface->w, surface->h))
103
0
      goto fail;
104
105
0
    if ((nXDst > INT32_MAX) || (nYDst > INT32_MAX) || (width > INT32_MAX) ||
106
0
        (height > INT32_MAX))
107
0
      goto fail;
108
109
0
    rc = gdi_InvalidateRegion(gdi->primary->hdc, (INT32)nXDst, (INT32)nYDst, (INT32)width,
110
0
                              (INT32)height);
111
0
  }
112
0
fail:
113
114
0
  if (!update_end_paint(update))
115
0
    return FALSE;
116
117
0
  return rc;
118
0
}
119
120
static BOOL gdiVideoDeleteSurface(VideoClientContext* video, VideoSurface* surface)
121
0
{
122
0
  WINPR_UNUSED(video);
123
0
  VideoClient_DestroyCommonContext(surface);
124
0
  return TRUE;
125
0
}
126
127
void gdi_video_control_init(rdpGdi* gdi, VideoClientContext* video)
128
0
{
129
0
  WINPR_ASSERT(gdi);
130
0
  WINPR_ASSERT(video);
131
132
0
  gdi->video = video;
133
0
  video->custom = gdi;
134
0
  video->createSurface = gdiVideoCreateSurface;
135
0
  video->showSurface = gdiVideoShowSurface;
136
0
  video->deleteSurface = gdiVideoDeleteSurface;
137
0
  video->setGeometry(video, gdi->geometry);
138
0
}
139
140
void gdi_video_control_uninit(rdpGdi* gdi, WINPR_ATTR_UNUSED VideoClientContext* video)
141
0
{
142
0
  WINPR_ASSERT(gdi);
143
0
  gdi->video = NULL;
144
0
}
145
146
void gdi_video_data_init(WINPR_ATTR_UNUSED rdpGdi* gdi, WINPR_ATTR_UNUSED VideoClientContext* video)
147
0
{
148
0
  WINPR_ASSERT(gdi);
149
0
  WINPR_ASSERT(gdi->context);
150
0
}
151
152
void gdi_video_data_uninit(WINPR_ATTR_UNUSED rdpGdi* gdi,
153
                           WINPR_ATTR_UNUSED VideoClientContext* context)
154
0
{
155
0
  WINPR_ASSERT(gdi);
156
0
  WINPR_ASSERT(gdi->context);
157
0
}
158
159
VideoSurface* VideoClient_CreateCommonContext(size_t size, UINT32 x, UINT32 y, UINT32 w, UINT32 h)
160
0
{
161
0
  VideoSurface* ret = NULL;
162
163
0
  WINPR_ASSERT(size >= sizeof(VideoSurface));
164
165
0
  ret = calloc(1, size);
166
0
  if (!ret)
167
0
    return NULL;
168
169
0
  ret->format = PIXEL_FORMAT_BGRX32;
170
0
  ret->x = x;
171
0
  ret->y = y;
172
0
  ret->w = w;
173
0
  ret->h = h;
174
0
  ret->alignedWidth = ret->w + 32 - ret->w % 16;
175
0
  ret->alignedHeight = ret->h + 32 - ret->h % 16;
176
177
0
  ret->scanline = ret->alignedWidth * FreeRDPGetBytesPerPixel(ret->format);
178
0
  ret->data = winpr_aligned_malloc(1ull * ret->scanline * ret->alignedHeight, 64);
179
0
  if (!ret->data)
180
0
    goto fail;
181
0
  return ret;
182
0
fail:
183
0
  VideoClient_DestroyCommonContext(ret);
184
0
  return NULL;
185
0
}
186
187
void VideoClient_DestroyCommonContext(VideoSurface* surface)
188
0
{
189
0
  if (!surface)
190
0
    return;
191
0
  winpr_aligned_free(surface->data);
192
0
  free(surface);
193
0
}