aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/vid_ddraw.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/vid_ddraw.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/vid_ddraw.cpp')
-rw-r--r--Src/Winamp/vid_ddraw.cpp980
1 files changed, 980 insertions, 0 deletions
diff --git a/Src/Winamp/vid_ddraw.cpp b/Src/Winamp/vid_ddraw.cpp
new file mode 100644
index 00000000..42c81c58
--- /dev/null
+++ b/Src/Winamp/vid_ddraw.cpp
@@ -0,0 +1,980 @@
+#include <ddraw.h>
+#include <multimon.h>
+#include "main.h"
+#include "vid_subs.h"
+#include "vid_ddraw.h"
+#include "directdraw.h"
+#include "WinampAttributes.h"
+#include "../nsutil/image.h"
+
+DDrawVideoOutput ddrawVideo;
+#define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
+
+DDrawVideoOutput::DDrawVideoOutput()
+{
+ lpDD = NULL;
+ lpddsOverlay = NULL;
+ lastresizerect.bottom = 0;
+ lastresizerect.top = 0;
+ lastresizerect.left = 0;
+ lastresizerect.right = 0;
+
+ lpddsPrimary = NULL;
+ lpddsClipper = NULL;
+ lpddsSTTemp = NULL;
+
+ width = height = flip = 0;
+ type = VIDEO_MAKETYPE('Y', 'V', '1', '2');
+ uDestSizeAlign = uSrcSizeAlign = 0;
+ dwUpdateFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
+ m_depth = 16;
+
+ initing = false;
+ needchange = 0;
+ m_palette = NULL;
+ m_lastsubtitle = NULL;
+ sttmp_w = sttmp_h = 0;
+ subFont = NULL;
+ m_sub_needremeasure = 0;
+ m_fontsize = 0;
+ memset(&winRect, 0, sizeof(winRect));
+}
+
+void DDrawVideoOutput::close()
+{
+ if (lpddsSTTemp) lpddsSTTemp->Release(); lpddsSTTemp = 0;
+ if (lpddsPrimary) lpddsPrimary->Release(); lpddsPrimary = 0;
+ if (lpddsOverlay) lpddsOverlay->Release(); lpddsOverlay = 0;
+ if (lpddsClipper) lpddsClipper->Release(); lpddsClipper = 0;
+ if (lpDD) lpDD->Release(); lpDD = 0;// BU added NULL check in response to talkback
+ if (subFont) DeleteObject(subFont); subFont = 0;
+// removeFullScreen();
+}
+DDrawVideoOutput::~DDrawVideoOutput()
+{
+ DDrawVideoOutput::close();
+}
+
+void DDrawVideoOutput::drawSubtitle(SubsItem *item)
+{
+ m_lastsubtitle = item;
+ m_sub_needremeasure = 1;
+}
+
+int DDrawVideoOutput::create(HWND parent, VideoAspectAdjuster *_adjuster, int w, int h, unsigned int ptype, int flipit, double aspectratio)
+{
+ needchange = 0;
+ this->parent = parent;
+ m_lastsubtitle = NULL;
+ type = ptype;
+ width = w;
+ height = h;
+ flip = flipit;
+ adjuster = _adjuster;
+
+ initing = true;
+ HWND hwnd = this->parent;
+
+ if (lpDD) lpDD->Release();
+ lpDD = NULL;
+
+ update_monitor_coords();
+
+ if (_DirectDrawCreate)
+ {
+ if (!foundGUID) _DirectDrawCreate(NULL, &lpDD, NULL);
+ else _DirectDrawCreate(&m_devguid, &lpDD, NULL);
+ }
+
+ if (!lpDD)
+ {
+ initing = false;
+ return 0;
+ }
+
+ lpDD->SetCooperativeLevel(hwnd, DDSCL_NOWINDOWCHANGES | DDSCL_NORMAL);
+
+ DDSURFACEDESC ddsd;
+ INIT_DIRECTDRAW_STRUCT(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpddsPrimary, NULL);
+
+ if (FAILED(ddrval) || !lpddsPrimary)
+ {
+ initing = false;
+ return 0;
+ }
+
+ HRESULT v = -1;
+ DDSURFACEDESC DDsd = {sizeof(DDsd), };
+ lpddsPrimary->GetSurfaceDesc(&ddsd);
+ DDsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; //create the surface at screen depth
+ DDsd.dwWidth = w;
+ DDsd.dwHeight = h;
+ DDsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN;
+ if (config_video_ddraw) v = lpDD->CreateSurface(&DDsd, &lpddsOverlay, NULL);
+ if (!config_video_ddraw || FAILED(v))
+ {
+ // fall back to system memory if video mem doesn't work
+ DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
+ v = lpDD->CreateSurface(&DDsd, &lpddsOverlay, NULL);
+ }
+ if (FAILED(v))
+ {
+ // this video card sucks then :)
+ lpddsOverlay = NULL;
+ initing = false;
+ return 0;
+ }
+
+ // get the depth
+ m_depth = 8;
+ INIT_DIRECTDRAW_STRUCT(m_ddpf);
+ if (lpddsOverlay->GetPixelFormat(&m_ddpf) >= 0)
+ {
+ m_depth = m_ddpf.dwRGBBitCount;
+ if (m_depth == 16 && m_ddpf.dwGBitMask == 0x03e0) m_depth = 15;
+ }
+
+ if (lpDD->CreateClipper(0, &lpddsClipper, NULL) != DD_OK)
+ {
+ lpddsClipper = NULL;
+ initing = false;
+ return 0;
+ }
+
+ lpddsClipper->SetHWnd(0, hwnd);
+ lpddsPrimary->SetClipper(lpddsClipper);
+ initing = false;
+
+ //get current monitor
+ getViewport(&m_monRect, hwnd, 1, NULL);
+
+ return 1;
+}
+
+bool DDrawVideoOutput::Paint(HWND hwnd)
+{
+ RECT r;
+ GetClientRect(hwnd, &r);
+ RECT fullr = r;
+ adjuster->adjustAspect(r);
+ if (r.left != lastresizerect.left || r.right != lastresizerect.right || r.top != lastresizerect.top ||
+ r.bottom != lastresizerect.bottom)
+ {
+ if (r.left != 0)
+ {
+ RECT tmp = {0, 0, r.left, fullr.bottom};
+ InvalidateRect(hwnd, &tmp, TRUE);
+ }
+
+ if (r.right != fullr.right)
+ {
+ RECT tmp = {r.right, 0, fullr.right, fullr.bottom};
+ InvalidateRect(hwnd, &tmp, TRUE);
+ }
+ if (r.top != 0)
+ {
+ RECT tmp = {r.left, 0, r.right, r.top};
+ InvalidateRect(hwnd, &tmp, TRUE);
+ }
+ if (r.bottom != fullr.bottom)
+ {
+ RECT tmp = {r.left, r.bottom, r.right, fullr.bottom};
+ InvalidateRect(hwnd, &tmp, TRUE);
+ }
+
+ lastresizerect = r;
+ }
+
+ ClientToScreen(hwnd, (LPPOINT)&r);
+ ClientToScreen(hwnd, ((LPPOINT)&r) + 1);
+
+ // transform coords from windows desktop coords (where 0,0==upper-left corner of box encompassing all monitors)
+ // to the coords for the monitor we're displaying on:
+ r.left -= m_mon_x;
+ r.right -= m_mon_x;
+ r.top -= m_mon_y;
+ r.bottom -= m_mon_y;
+
+ HDC hdc = NULL;
+ HDC inhdc = NULL;
+
+ RECT *pSrcRect = NULL;
+
+
+ int needst = 0;
+
+
+ SubsItem *mlst = m_lastsubtitle;
+ if (mlst)
+ {
+ int curw = r.right - r.left, curh = r.bottom - r.top;
+ if (!lpddsSTTemp || sttmp_w != curw || sttmp_h != curh)
+ {
+ if (lpddsSTTemp) lpddsSTTemp->Release();
+ lpddsSTTemp = 0;
+
+ HRESULT v = -1;
+ DDSURFACEDESC DDsd = {sizeof(DDsd), };
+ DDSURFACEDESC ddsd;
+ INIT_DIRECTDRAW_STRUCT(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ lpddsPrimary->GetSurfaceDesc(&ddsd);
+ DDsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; //create the surface at screen depth
+ DDsd.dwWidth = sttmp_w = curw;
+ DDsd.dwHeight = sttmp_h = curh;
+ DDsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
+ if (config_video_ddraw) v = lpDD->CreateSurface(&DDsd, &lpddsSTTemp, NULL);
+ if (!config_video_ddraw || FAILED(v))
+ {
+ // fall back to system memory if video mem doesn't work
+ DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
+ lpDD->CreateSurface(&DDsd, &lpddsSTTemp, NULL);
+ }
+ m_sub_needremeasure = 1;
+ }
+ if (lpddsSTTemp) needst = 1;
+ }
+
+ if (needst)
+ {
+ HDC tmpdc = NULL;
+ if (!config_video_ddraw || lpddsSTTemp->Blt(NULL, lpddsOverlay, NULL, DDBLT_WAIT, 0) != DD_OK)
+ {
+ // as a last resort, BitBlt().
+ HDC tmpdc2;
+ if (lpddsOverlay->GetDC(&tmpdc2) == DD_OK)
+ {
+ if (lpddsSTTemp->GetDC(&tmpdc) == DD_OK)
+ {
+ BitBlt(tmpdc, 0, 0, sttmp_w, sttmp_h, tmpdc2, 0, 0, SRCCOPY);
+ }
+ }
+ }
+
+ if (mlst && (tmpdc || lpddsSTTemp->GetDC(&tmpdc) == DD_OK))
+ {
+ int m_lastsubxp = mlst->xPos;
+ int m_lastsubyp = mlst->yPos;
+
+ RECT oldwinRect = winRect;
+ GetClientRect(hwnd, &winRect);
+ if (!subFont || ((winRect.bottom - winRect.top) != (oldwinRect.bottom - oldwinRect.top)) || m_fontsize != mlst->fontSize)
+ {
+ if (subFont) DeleteObject(subFont);
+ m_fontsize = mlst->fontSize;
+ subFont = CreateFontA(14 + m_fontsize + 18 * (winRect.bottom - winRect.top) / 768, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
+ }
+
+ HGDIOBJ oldobj = SelectObject(tmpdc, subFont);
+
+ int centerflags = 0;
+ if (m_lastsubxp < 127) centerflags |= DT_LEFT;
+ else if (m_lastsubxp > 127) centerflags |= DT_RIGHT;
+ else centerflags |= DT_CENTER;
+
+ if (m_lastsubyp < 127) centerflags |= DT_TOP;
+ else if (m_lastsubyp > 127) centerflags |= DT_BOTTOM;
+
+ if (m_sub_needremeasure && mlst)
+ {
+ subRect = r;
+ subRect.bottom -= subRect.top;
+ subRect.right -= subRect.left;
+ subRect.top = subRect.left = 0;
+
+ SIZE s;
+ GetTextExtentPoint32A(tmpdc, mlst->text, lstrlenA(mlst->text), &s);
+
+ // calcul for multiline text
+ const char *p = mlst->text;
+ int n = 0;
+ while (*p != 0) if (*p++ == '\n') n++;
+ if (n) s.cy *= (n + 1);
+
+ if (m_lastsubxp > 127) // towards the right
+ {
+ subRect.right -= ((subRect.right - subRect.left) * (255 - m_lastsubxp)) / 256;
+ }
+ else if (m_lastsubxp < 127)
+ {
+ subRect.left += ((subRect.right - subRect.left) * m_lastsubxp) / 256;
+ }
+
+ subRect.top += ((subRect.bottom - s.cy - subRect.top) * m_lastsubyp) / 255;
+
+ subRect.bottom = subRect.top + s.cy;
+ }
+
+ SetBkMode(tmpdc, TRANSPARENT);
+
+ // draw outline
+ SetTextColor(tmpdc, RGB(0, 0, 0));
+ int y = 1;
+ int x = 1;
+ RECT r2 = {subRect.left + x, subRect.top + y, subRect.right + x, subRect.bottom + y};
+ if (mlst)
+ {
+ DrawTextA(tmpdc, mlst->text, -1, &r2, centerflags | DT_NOCLIP | DT_NOPREFIX);
+ // draw text
+ SetTextColor(tmpdc, RGB(mlst->colorRed, mlst->colorGreen, mlst->colorBlue));
+ DrawTextA(tmpdc, mlst->text, -1, &subRect, centerflags | DT_NOCLIP | DT_NOPREFIX);
+ }
+ SelectObject(tmpdc, oldobj);
+ lpddsSTTemp->ReleaseDC(tmpdc);
+ }
+ if (!config_video_ddraw || lpddsPrimary->Blt(&r, lpddsSTTemp, pSrcRect, DDBLT_WAIT, 0) != DD_OK)
+ {
+ // as a last resort, BitBlt().
+ if (lpddsOverlay->GetDC(&inhdc) != DD_OK)
+ {
+ needchange = 1;
+ return false;
+ }
+ if (lpddsPrimary->GetDC(&hdc) != DD_OK)
+ {
+ lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
+ needchange = 1;
+ return false;
+ }
+
+ int src_w = width;
+ int src_h = pSrcRect ? (pSrcRect->bottom - pSrcRect->top) : height;
+ if (r.right - r.left == src_w && r.bottom - r.top == src_h)
+ BitBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, SRCCOPY);
+ else
+ StretchBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, src_w, src_h, SRCCOPY);
+ }
+ }
+ else
+ {
+ if (!config_video_ddraw || lpddsPrimary->Blt(&r, lpddsOverlay, pSrcRect, DDBLT_WAIT, 0) != DD_OK)
+ {
+ // as a last resort, BitBlt().
+ if (lpddsOverlay->GetDC(&inhdc) != DD_OK)
+ {
+ needchange = 1;
+ return false;
+ }
+ if (lpddsPrimary->GetDC(&hdc) != DD_OK)
+ {
+ lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
+ needchange = 1;
+ return false;
+ }
+
+ int src_w = width;
+ int src_h = pSrcRect ? (pSrcRect->bottom - pSrcRect->top) : height;
+ if (r.right - r.left == src_w && r.bottom - r.top == src_h)
+ BitBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, SRCCOPY);
+ else
+ StretchBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, src_w, src_h, SRCCOPY);
+ }
+ }
+
+ if (hdc)
+ {
+ lpddsPrimary->ReleaseDC(hdc); hdc = NULL;
+ }
+ if (inhdc)
+ {
+ lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
+ }
+
+ return true;
+}
+
+int DDrawVideoOutput::onPaint(HWND hwnd)
+{
+ // reblit the last frame
+ if (lpddsPrimary)
+ {
+ PAINTSTRUCT p;
+ BeginPaint(hwnd, &p);
+
+ RECT r;
+
+ GetClientRect(hwnd, &r);
+
+ HRGN hrgn = CreateRectRgnIndirect(&r);
+ HBRUSH b = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ FillRgn(p.hdc, hrgn, b);
+ DeleteObject(b);
+ DeleteObject(hrgn);
+
+ if (Paint(hwnd))
+ {
+ EndPaint(hwnd, &p);
+
+ return 1;
+ }
+ EndPaint(hwnd, &p);
+ }
+ return 0;
+
+}
+
+bool DDrawVideoOutput::LockSurface(DDSURFACEDESC *dd)
+{
+ for (;;Sleep(0))
+ {
+ HRESULT hr = lpddsOverlay->Lock(0, dd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
+
+ if (dd->lpSurface)
+ break;
+
+ if (hr == DDERR_SURFACELOST)
+ {
+ lpddsPrimary->Restore();
+ lpddsOverlay->Restore();
+ hr = lpddsOverlay->Lock(0, dd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
+ if (hr == DDERR_SURFACELOST)
+ return false;
+ }
+ else if (hr != DDERR_WASSTILLDRAWING)
+ return false;
+ }
+
+ return true;
+}
+
+void DDrawVideoOutput::displayFrame(const char *buf, int size, int time)
+{
+ DDSURFACEDESC dd = {sizeof(dd), };
+ if (config_video_vsync2) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
+
+ if (!LockSurface(&dd))
+ {
+ needchange = 1;
+ return ;
+ }
+ if (type == VIDEO_MAKETYPE('Y', 'V', '1', '2'))
+ {
+ const YV12_PLANES *planes = (YV12_PLANES *)buf;
+ // convert yv12 to rgb
+ int bytes = m_depth >> 3;
+ if (m_depth == 15) bytes = 2;
+ int i, j, y00, y01, y10, y11, u, v;
+ unsigned char *pY = (unsigned char *)planes->y.baseAddr;
+ unsigned char *pU = (unsigned char *)planes->u.baseAddr;
+ unsigned char *pV = (unsigned char *)planes->v.baseAddr;
+ unsigned char *pOut = (unsigned char*)dd.lpSurface;
+ const int rvScale = (int)(2.017 * 65536.0); //91881;
+ const int gvScale = - (int)(0.392 * 65536.0); // -22553;
+ const int guScale = - (int)(0.813 * 65536.0); // -46801;
+ const int buScale = (int)(1.596 * 65536.0); //116129;
+ const int yScale = (int)(1.164 * 65536.0); //(1.164*65536.0);
+ int addOut = dd.lPitch * 2 - width * bytes;
+ int yrb = planes->y.rowBytes;
+ int addL = dd.lPitch;
+
+ /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
+#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
+
+ if (flip)
+ {
+ pOut += (dd.lPitch) * (height - 1);
+ addOut = -dd.lPitch * 2 - width * bytes;
+ addL = -addL;
+ }
+
+ for (j = 0; j <= height - 2; j += 2)
+ {
+ for (i = 0; i <= width - 2; i += 2)
+ {
+ y00 = *pY - 16;
+ y01 = *(pY + 1) - 16;
+ y10 = *(pY + yrb) - 16;
+ y11 = *(pY + yrb + 1) - 16;
+ u = (*pU++) - 128;
+ v = (*pV++) - 128;
+
+ {
+ int r, g, b;
+
+ g = guScale * v + gvScale * u;
+ r = buScale * v;
+ b = rvScale * u;
+
+ y00 *= yScale; y01 *= yScale;
+ y10 *= yScale; y11 *= yScale;
+
+ switch (m_depth)
+ {
+ case 15:
+ {
+ unsigned short *rgb = (unsigned short *)pOut;
+ rgb[0] = ((LIMIT(r + y00) >> 3) << 10) | ((LIMIT(g + y00) >> 3) << 5) | (LIMIT(b + y00) >> 3);
+ rgb[1] = ((LIMIT(r + y01) >> 3) << 10) | ((LIMIT(g + y01) >> 3) << 5) | (LIMIT(b + y01) >> 3);
+ rgb += addL / 2;
+ rgb[0] = ((LIMIT(r + y10) >> 3) << 10) | ((LIMIT(g + y10) >> 3) << 5) | (LIMIT(b + y10) >> 3);
+ rgb[1] = ((LIMIT(r + y11) >> 3) << 10) | ((LIMIT(g + y11) >> 3) << 5) | (LIMIT(b + y11) >> 3);
+ }
+ break;
+ case 16:
+ {
+ unsigned short *rgb = (unsigned short *)pOut;
+ rgb[0] = ((LIMIT(r + y00) >> 3) << 11) | ((LIMIT(g + y00) >> 2) << 5) | (LIMIT(b + y00) >> 3);
+ rgb[1] = ((LIMIT(r + y01) >> 3) << 11) | ((LIMIT(g + y01) >> 2) << 5) | (LIMIT(b + y01) >> 3);
+ rgb += addL / 2;
+ rgb[0] = ((LIMIT(r + y10) >> 3) << 11) | ((LIMIT(g + y10) >> 2) << 5) | (LIMIT(b + y10) >> 3);
+ rgb[1] = ((LIMIT(r + y11) >> 3) << 11) | ((LIMIT(g + y11) >> 2) << 5) | (LIMIT(b + y11) >> 3);
+ }
+ break;
+ case 24:
+ {
+ unsigned char *rgb = pOut;
+ /* Write out top two pixels */
+ rgb[0] = LIMIT(b + y00); rgb[1] = LIMIT(g + y00); rgb[2] = LIMIT(r + y00);
+ rgb[3] = LIMIT(b + y01); rgb[4] = LIMIT(g + y01); rgb[5] = LIMIT(r + y01);
+
+ /* Skip down to next line to write out bottom two pixels */
+ rgb += addL;
+ rgb[0] = LIMIT(b + y10); rgb[1] = LIMIT(g + y10); rgb[2] = LIMIT(r + y10);
+ rgb[3] = LIMIT(b + y11); rgb[4] = LIMIT(g + y11); rgb[5] = LIMIT(r + y11);
+ }
+ break;
+ case 32:
+ {
+ unsigned char *rgb = pOut;
+ /* Write out top two pixels */
+ rgb[0] = LIMIT(b + y00); rgb[1] = LIMIT(g + y00); rgb[2] = LIMIT(r + y00);
+ rgb[4] = LIMIT(b + y01); rgb[5] = LIMIT(g + y01); rgb[6] = LIMIT(r + y01);
+
+ /* Skip down to next line to write out bottom two pixels */
+ rgb += addL;
+ rgb[0] = LIMIT(b + y10); rgb[1] = LIMIT(g + y10); rgb[2] = LIMIT(r + y10);
+ rgb[4] = LIMIT(b + y11); rgb[5] = LIMIT(g + y11); rgb[6] = LIMIT(r + y11);
+ }
+ break;
+ }
+ }
+
+ pY += 2;
+ pOut += 2 * bytes;
+ }
+ pY += yrb + yrb - width;
+ pU += planes->u.rowBytes - width / 2;
+ pV += planes->v.rowBytes - width / 2;
+ pOut += addOut;
+ }
+ }
+ else if (type == VIDEO_MAKETYPE('R', 'G', '3', '2'))
+ {
+ //FUCKO: do we need to support 8bits depth?
+ switch (m_depth)
+ {
+ case 15:
+ { // convert RGB32 -> RGB16 (555)
+ const char *a = buf;
+ char *b = (char *)dd.lpSurface;
+ int l = width * 4, l2 = dd.lPitch;
+ int ladj = l;
+ if (flip)
+ {
+ a += l * (height - 1); ladj = -ladj;
+ }
+ for (int i = 0;i < height;i++)
+ {
+ short *dest = (short *)b;
+ int *src = (int *)a;
+ for (int j = 0;j < width;j++)
+ {
+ int c = *(src++);
+ int r = c >> 16;
+ int g = (c >> 8) & 0xff;
+ int b = (c) & 0xff;
+ *(dest++) = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+ }
+ a += ladj; b += l2;
+ }
+ }
+ break;
+ case 16:
+ { // convert RGB32 -> RGB16
+ //FUCKO: this assumes 565
+ const char *a = buf;
+ char *b = (char *)dd.lpSurface;
+ int l = width * 4, l2 = dd.lPitch;
+ int ladj = l;
+ if (flip)
+ {
+ a += l * (height - 1); ladj = -ladj;
+ }
+ for (int i = 0;i < height;i++)
+ {
+ short *dest = (short *)b;
+ int *src = (int *)a;
+ for (int j = 0;j < width;j++)
+ {
+ //FUCKO: optimize here
+ int c = *(src++);
+ int r = c >> 16;
+ int g = (c >> 8) & 0xff;
+ int b = (c) & 0xff;
+ *(dest++) = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+ }
+ a += ladj; b += l2;
+ }
+ }
+ break;
+ case 24:
+ { // convert RGB32 -> RGB24
+ const char *a = buf;
+ char *b = (char *)dd.lpSurface;
+ int l = width * 4, l2 = dd.lPitch;
+ int ladj = l;
+ if (flip)
+ {
+ a += l * (height - 1); ladj = -ladj;
+ }
+ for (int i = 0;i < height;i++)
+ {
+ char *dest = (char *)b;
+ int *src = (int *)a;
+ for (int j = 0;j < width;j++)
+ {
+ //FUCKO: optimize here
+ int c = *(src++);
+ int r = c >> 16;
+ int g = (c >> 8) & 0xff;
+ int b = (c) & 0xff;
+ *dest++ = b;
+ *dest++ = g;
+ *dest++ = r;
+ }
+ a += ladj; b += l2;
+ }
+ }
+ break;
+ case 32:
+ { // straight RGB32 copy
+ if (flip)
+ nsutil_image_CopyFlipped_U8((uint8_t *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*4, width, height);
+ else
+ nsutil_image_Copy_U8((uint8_t *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*4, width, height);
+ }
+ break;
+ }
+ }
+ else if (type == VIDEO_MAKETYPE('Y', 'U', 'Y', '2') || type == VIDEO_MAKETYPE('U', 'Y', 'V', 'Y'))
+ {
+ //const char *a = buf;
+ char *b = (char *)dd.lpSurface;
+ int /*l = width * 2, */l2 = dd.lPitch;
+ if (flip)
+ {
+ b += (height - 1) * l2;
+ l2 = -l2;
+ }
+ switch (m_depth)
+ {
+ case 15:
+ {
+ // yuy2->rgb16 (555) conversion
+ unsigned char *src = (unsigned char *)buf;
+ unsigned short *dst = (unsigned short *)dd.lpSurface;
+ int line, col; //, linewidth;
+ int y, yy;
+ int u, v;
+ int vr, ug, vg, ub;
+ unsigned char *py, *pu, *pv;
+
+ //linewidth = width - (width >> 1);
+ py = src;
+ pu = src + 1;
+ pv = src + 3;
+
+ int pitchadd = dd.lPitch / 2 - width;
+
+ for (line = 0; line < height; line++)
+ {
+ for (col = 0; col < width; col++)
+ {
+#undef LIMIT
+#define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
+
+ y = *py;
+ yy = y << 8;
+ u = *pu - 128;
+ ug = 88 * u;
+ ub = 454 * u;
+ v = *pv - 128;
+ vg = 183 * v;
+ vr = 359 * v;
+
+ unsigned char b = LIMIT(yy + ub);
+ unsigned char g = LIMIT(yy - ug - vg);
+ unsigned char r = LIMIT(yy + vr);
+ *(dst++) = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+
+ py += 2;
+ if ((col & 1) == 1)
+ {
+ pu += 4; // skip yvy every second y
+ pv += 4; // skip yuy every second y
+ }
+ } // ..for col
+ dst += pitchadd;
+ } /* ..for line */
+ }
+ break;
+ case 16:
+ {
+ // yuy2->rgb16 conversion
+ //FUCKO: only supports 565
+ unsigned char *src = (unsigned char *)buf;
+ unsigned short *dst = (unsigned short *)dd.lpSurface;
+ int line, col; //, linewidth;
+ int y, yy;
+ int u, v;
+ int vr, ug, vg, ub;
+ unsigned char *py, *pu, *pv;
+
+ //linewidth = width - (width >> 1);
+ py = src;
+ pu = src + 1;
+ pv = src + 3;
+
+ int pitchadd = dd.lPitch / 2 - width;
+
+ for (line = 0; line < height; line++)
+ {
+ for (col = 0; col < width; col++)
+ {
+#undef LIMIT
+#define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
+
+ y = *py;
+ yy = y << 8;
+ u = *pu - 128;
+ ug = 88 * u;
+ ub = 454 * u;
+ v = *pv - 128;
+ vg = 183 * v;
+ vr = 359 * v;
+
+ unsigned char b = LIMIT(yy + ub);
+ unsigned char g = LIMIT(yy - ug - vg);
+ unsigned char r = LIMIT(yy + vr);
+ *(dst++) = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+
+ py += 2;
+ if ((col & 1))
+ {
+ pu += 4; // skip yvy every second y
+ pv += 4; // skip yuy every second y
+ }
+ } // ..for col
+ dst += pitchadd;
+ } /* ..for line */
+ }
+ break;
+ case 24:
+ {
+ // yuy2->rgb24 conversion
+ unsigned char *src = (unsigned char *)buf;
+ unsigned char *dst = (unsigned char *)dd.lpSurface;
+ int line, col; //, linewidth;
+ int y, yy;
+ int u, v;
+ int vr, ug, vg, ub;
+ unsigned char *py, *pu, *pv;
+
+ //linewidth = width - (width >> 1);
+ py = src;
+ pu = src + 1;
+ pv = src + 3;
+
+ int pitchadd = dd.lPitch - (width * 3);
+
+ for (line = 0; line < height; line++)
+ {
+ for (col = 0; col < width; col++)
+ {
+#undef LIMIT
+#define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
+
+ y = *py;
+ yy = y << 8;
+ u = *pu - 128;
+ ug = 88 * u;
+ ub = 454 * u;
+ v = *pv - 128;
+ vg = 183 * v;
+ vr = 359 * v;
+
+ *(dst++) = LIMIT(yy + ub);
+ *(dst++) = LIMIT(yy - ug - vg);
+ *(dst++) = LIMIT(yy + vr);
+
+ py += 2;
+ if ((col & 1) == 1)
+ {
+ pu += 4; // skip yvy every second y
+ pv += 4; // skip yuy every second y
+ }
+ } // ..for col
+ dst += pitchadd;
+ } /* ..for line */
+ }
+ break;
+ case 32:
+ {
+ // yuy2->rgb32 conversion
+ unsigned char *src = (unsigned char *)buf;
+ unsigned char *dst = (unsigned char *)dd.lpSurface;
+ int line, col; //, linewidth;
+ int y, yy;
+ int u, v;
+ int vr, ug, vg, ub;
+ unsigned char *py, *pu, *pv;
+
+ //linewidth = width - (width >> 1);
+ py = src;
+ pu = src + 1;
+ pv = src + 3;
+
+ int pitchadd = dd.lPitch - (width * 4);
+
+ for (line = 0; line < height; line++)
+ {
+ for (col = 0; col < width; col++)
+ {
+#undef LIMIT
+#define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
+
+ y = *py;
+ yy = y << 8;
+ u = *pu - 128;
+ ug = 88 * u;
+ ub = 454 * u;
+ v = *pv - 128;
+ vg = 183 * v;
+ vr = 359 * v;
+
+ *dst++ = LIMIT(yy + ub); // b
+ *dst++ = LIMIT(yy - ug - vg); // g
+ *dst++ = LIMIT(yy + vr); // r
+ dst++;
+
+ py += 2;
+ if ((col & 1) == 1)
+ {
+ pu += 4; // skip yvy every second y
+ pv += 4; // skip yuy every second y
+ }
+ } // ..for col
+ dst += pitchadd;
+ } /* ..for line */
+ }
+ break;
+ }
+ }
+ else if (type == VIDEO_MAKETYPE('R', 'G', '2', '4'))
+ {
+ //FUCKO: only ->RGB32 conversion supported
+ switch (m_depth)
+ {
+ case 32:
+ {
+ if (flip)
+ nsutil_image_ConvertFlipped_RGB24_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*3, width, height);
+ else
+ nsutil_image_Convert_RGB24_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*3, width, height);
+
+ }
+ break;
+ }
+ }
+ else if (type == VIDEO_MAKETYPE('R', 'G', 'B', '8') && m_palette)
+ {
+ unsigned char *d = (unsigned char *)dd.lpSurface;
+ int pitch = dd.lPitch;
+ unsigned char *src = (unsigned char *)buf;
+ int newwidth = (width + 3) & 0xfffc;
+ src += newwidth * height - 1;
+ for (int j = 0;j < height;j++)
+ {
+ switch (m_depth)
+ {
+ case 15:
+ case 16:
+ {
+ unsigned short *dest = (unsigned short *)d;
+ for (int i = 0;i < newwidth;i++)
+ {
+ unsigned char c = src[ -newwidth + 1 + i];
+ RGBQUAD *rgb = &m_palette[c];
+ switch (m_depth)
+ {
+ case 15: *(dest++) = ((rgb->rgbRed >> 3) << 10) | ((rgb->rgbGreen >> 3) << 5) | (rgb->rgbBlue >> 3); break;
+ case 16: *(dest++) = ((rgb->rgbRed >> 3) << 11) | ((rgb->rgbGreen >> 2) << 5) | (rgb->rgbBlue >> 3); break;
+ }
+ }
+ }
+ break;
+ case 24:
+ {
+ unsigned char *dest = d;
+ for (int i = 0;i < newwidth;i++)
+ {
+ unsigned char c = src[ -newwidth + 1 + i];
+ RGBQUAD *rgb = &m_palette[c];
+ *dest++ = rgb->rgbBlue;
+ *dest++ = rgb->rgbGreen;
+ *dest++ = rgb->rgbRed;
+ if (m_depth == 32) dest++;
+ }
+ }
+ break;
+ case 32:
+ if (flip)
+ nsutil_image_PaletteFlipped_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width, width, height, (RGB32 *)m_palette);
+ else
+ nsutil_image_Palette_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width, width, height, (RGB32 *)m_palette);
+ break;
+ }
+ d += pitch;
+ src -= newwidth;
+ }
+ }
+
+ lpddsOverlay->Unlock(&dd);
+
+
+ HWND hwnd = this->parent;
+ if (!IsWindow(hwnd)) return ;
+
+ // if(GetParent(hwnd)) hwnd=GetParent(hwnd);
+
+ Paint(hwnd);
+}
+
+
+
+void DDrawVideoOutput::timerCallback()
+{
+ //check if the video has been dragged to another monitor
+ RECT curRect;
+
+ getViewport(&curRect, parent, 1, NULL);
+ if (memcmp(&curRect, &m_monRect, sizeof(RECT)))
+ needchange = 1;
+}
+
+
+void DDrawVideoOutput::resetSubtitle()
+{
+ m_lastsubtitle = 0;
+}
+
+
+
+void DDrawVideoOutput::Refresh()
+{
+ // do nothing, we'll refresh on the next frame
+} \ No newline at end of file