diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/vid_ddraw.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Winamp/vid_ddraw.cpp')
-rw-r--r-- | Src/Winamp/vid_ddraw.cpp | 980 |
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 |