[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