[vlc-commits] [Git][videolan/vlc][master] 6 commits: wingdi: use less hacky way to set RGB values
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Sat Aug 5 10:07:55 UTC 2023
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
219ad8ea by Steve Lhomme at 2023-08-05T09:50:18+00:00
wingdi: use less hacky way to set RGB values
BITMAPINFO is actually BITMAPINFOHEADER and a dummy RGBQUAD.
It's better to have our own with the 3 fields. The red/green/blue fields were
not used, just taking enough space in the structure.
We could pass the proper sizeof in the BITMAPINFOHEADER when the 3 values
are used. It works with it on my machine, but it may not on older Windows
or older GPU drivers.
- - - - -
3cff2b38 by Steve Lhomme at 2023-08-05T09:50:18+00:00
wingdi: handle dynamic picture size change
It has to be done before the picture planes are updated.
- - - - -
088ae9eb by Steve Lhomme at 2023-08-05T09:50:18+00:00
wingdi: use the visible area display format
It doesn't matter if the source has some padding with a different pitch
than our buffer. The plane copies will work regardless.
- - - - -
e14aaa9a by Steve Lhomme at 2023-08-05T09:50:18+00:00
wingdi: use a plane to copy from the picture source
It's cleaner than using a dummy picture. We only support formats with a
single plane. And we don't need to recompute planes each time.
Also picture_UpdatePlanes() can fail (but not on RGB format). We don't need
to fix that.
- - - - -
a7575405 by Steve Lhomme at 2023-08-05T09:50:18+00:00
wingdi: make i_depth local
It's already stored in bih->biBitCount anyway.
- - - - -
e5d248af by Steve Lhomme at 2023-08-05T09:50:18+00:00
wingdi: fix plane pitch for RGB15
The values are stored on 16 bits, so we must not use biBitCount to compute
the pitch of a line but the actual number of bytes per pixel.
- - - - -
1 changed file:
- modules/video_output/win32/wingdi.c
Changes:
=====================================
modules/video_output/win32/wingdi.c
=====================================
@@ -61,21 +61,21 @@ typedef struct vout_display_sys_t
{
display_win32_area_t area;
- int i_depth;
-
/* Our offscreen bitmap and its framebuffer */
HDC off_dc;
HBITMAP off_bitmap;
- void *p_pic_buffer;
- int i_pic_pitch;
-
- struct
- {
- BITMAPINFO bitmapinfo;
- RGBQUAD red;
- RGBQUAD green;
- RGBQUAD blue;
+ plane_t pic_buf;
+
+ union {
+ BITMAPINFO bmiInfo;
+ struct
+ {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD red;
+ RGBQUAD green;
+ RGBQUAD blue;
+ } bi_rgb;
};
} vout_display_sys_t;
@@ -84,15 +84,68 @@ static void Display(vout_display_t *, picture_t *);
static int Init(vout_display_t *, video_format_t *);
static void Clean(vout_display_t *);
+static int ChangeSize(vout_display_t *vd, HDC hdc)
+{
+ vout_display_sys_t *sys = vd->sys;
+
+ // clear the background, even if creating the writable buffer fails
+ RECT display = {
+ .left = 0,
+ .right = vd->cfg->display.width,
+ .top = 0,
+ .bottom = vd->cfg->display.height,
+ };
+ FillRect(hdc, &display, GetStockObject(BLACK_BRUSH));
+
+ BITMAPINFOHEADER *bih = &sys->bi_rgb.bmiHeader;
+ if (bih->biWidth != (LONG)sys->area.src_fmt->i_visible_width ||
+ bih->biHeight != -(LONG)sys->area.src_fmt->i_visible_height)
+ {
+ if (sys->off_bitmap)
+ DeleteObject(sys->off_bitmap);
+
+ bih->biWidth = sys->area.src_fmt->i_visible_width;
+ bih->biHeight = -(LONG)sys->area.src_fmt->i_visible_height;
+ void *p_pic_buffer;
+ sys->off_bitmap = CreateDIBSection(hdc,
+ &sys->bmiInfo,
+ DIB_RGB_COLORS,
+ &p_pic_buffer, NULL, 0);
+ if (unlikely(sys->off_bitmap == NULL))
+ return VLC_EINVAL;
+ sys->pic_buf.p_pixels = p_pic_buffer;
+ sys->pic_buf.i_pixel_pitch = (bih->biBitCount + 7) / 8;
+ sys->pic_buf.i_pitch = sys->pic_buf.i_visible_pitch =
+ sys->area.src_fmt->i_visible_width * sys->pic_buf.i_pixel_pitch;
+ sys->pic_buf.i_lines = sys->pic_buf.i_visible_lines =
+ sys->area.src_fmt->i_visible_height;
+ }
+ return VLC_SUCCESS;
+}
+
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic,
vlc_tick_t date)
{
VLC_UNUSED(subpic);
VLC_UNUSED(date);
vout_display_sys_t *sys = vd->sys;
- picture_t fake_pic = *picture;
- picture_UpdatePlanes(&fake_pic, sys->p_pic_buffer, sys->i_pic_pitch);
- picture_CopyPixels(&fake_pic, picture);
+
+ if (sys->area.place_changed)
+ {
+ HDC hdc = GetDC(CommonVideoHWND(&sys->area));
+ int err = ChangeSize(vd, hdc);
+ ReleaseDC(CommonVideoHWND(&sys->area), hdc);
+
+ if (unlikely(err != VLC_SUCCESS))
+ return;
+
+ sys->area.place_changed = false;
+ }
+
+ assert((LONG)picture->format.i_visible_width == sys->bmiInfo.bmiHeader.biWidth &&
+ (LONG)picture->format.i_visible_height == -sys->bmiInfo.bmiHeader.biHeight);
+
+ plane_CopyPixels(&sys->pic_buf, picture->p);
}
static int Control(vout_display_t *vd, int query)
@@ -162,19 +215,6 @@ static void Display(vout_display_t *vd, picture_t *picture)
HDC hdc = GetDC(CommonVideoHWND(&sys->area));
- if (sys->area.place_changed)
- {
- /* clear the background */
- RECT display = {
- .left = 0,
- .right = vd->cfg->display.width,
- .top = 0,
- .bottom = vd->cfg->display.height,
- };
- FillRect(hdc, &display, GetStockObject(BLACK_BRUSH));
- sys->area.place_changed = false;
- }
-
SelectObject(sys->off_dc, sys->off_bitmap);
if (sys->area.place.width != vd->source->i_visible_width ||
@@ -209,12 +249,12 @@ static int Init(vout_display_t *vd, video_format_t *fmt)
HDC window_dc = GetDC(CommonVideoHWND(&sys->area));
/* */
- sys->i_depth = GetDeviceCaps(window_dc, PLANES) *
- GetDeviceCaps(window_dc, BITSPIXEL);
+ int i_depth = GetDeviceCaps(window_dc, PLANES) *
+ GetDeviceCaps(window_dc, BITSPIXEL);
/* */
- msg_Dbg(vd, "GDI depth is %i", sys->i_depth);
- switch (sys->i_depth) {
+ msg_Dbg(vd, "GDI depth is %i", i_depth);
+ switch (i_depth) {
case 8:
fmt->i_chroma = VLC_CODEC_RGB8;
break;
@@ -243,45 +283,35 @@ static int Init(vout_display_t *vd, video_format_t *fmt)
fmt->i_bmask = 0x000000ff;
break;
default:
- msg_Err(vd, "screen depth %i not supported", sys->i_depth);
+ msg_Err(vd, "screen depth %i not supported", i_depth);
+ ReleaseDC(CommonVideoHWND(&sys->area), window_dc);
return VLC_EGENERIC;
}
/* Initialize offscreen bitmap */
- BITMAPINFO *bi = &sys->bitmapinfo;
- memset(bi, 0, sizeof(BITMAPINFO) + 3 * sizeof(RGBQUAD));
- if (sys->i_depth > 8) {
- ((DWORD*)bi->bmiColors)[0] = fmt->i_rmask;
- ((DWORD*)bi->bmiColors)[1] = fmt->i_gmask;
- ((DWORD*)bi->bmiColors)[2] = fmt->i_bmask;
- }
+ sys->bmiInfo.bmiHeader = (BITMAPINFOHEADER) {
+ .biSize = sizeof(BITMAPINFOHEADER),
+ .biPlanes = 1,
+ .biBitCount = i_depth,
+ .biCompression = (i_depth == 15 ||
+ i_depth == 16) ? BI_BITFIELDS : BI_RGB,
+ };
- BITMAPINFOHEADER *bih = &sys->bitmapinfo.bmiHeader;
- bih->biSize = sizeof(BITMAPINFOHEADER);
- bih->biSizeImage = 0;
- bih->biPlanes = 1;
- bih->biCompression = (sys->i_depth == 15 ||
- sys->i_depth == 16) ? BI_BITFIELDS : BI_RGB;
- bih->biBitCount = sys->i_depth;
- bih->biWidth = fmt->i_width;
- bih->biHeight = -fmt->i_height;
- bih->biClrImportant = 0;
- bih->biClrUsed = 0;
- bih->biXPelsPerMeter = 0;
- bih->biYPelsPerMeter = 0;
-
- sys->i_pic_pitch = bih->biBitCount * bih->biWidth / 8;
- sys->off_bitmap = CreateDIBSection(window_dc,
- (BITMAPINFO *)bih,
- DIB_RGB_COLORS,
- &sys->p_pic_buffer, NULL, 0);
+ if (i_depth > 8) {
+ *((DWORD*)&sys->bi_rgb.red) = fmt->i_rmask;
+ *((DWORD*)&sys->bi_rgb.green) = fmt->i_gmask;
+ *((DWORD*)&sys->bi_rgb.blue) = fmt->i_bmask;
+ }
sys->off_dc = CreateCompatibleDC(window_dc);
- SelectObject(sys->off_dc, sys->off_bitmap);
+ int err = ChangeSize(vd, window_dc);
+ if (err != VLC_SUCCESS)
+ DeleteDC(sys->off_dc);
+
ReleaseDC(CommonVideoHWND(&sys->area), window_dc);
- return VLC_SUCCESS;
+ return err;
}
static void Clean(vout_display_t *vd)
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a5b564b7eeeae211beb590984bcbf8df22a182b6...e5d248af24e56956205bda2b8c599fc84f90120d
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a5b564b7eeeae211beb590984bcbf8df22a182b6...e5d248af24e56956205bda2b8c599fc84f90120d
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list