123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980 |
- #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
- }
|