00001 #include <map>
00002 #include <iostream>
00003 #include <algorithm>
00004 using namespace std;
00005
00006 #define _WIN32_WINNT 0x500
00007 #include "mythcontext.h"
00008 #include "videoout_dx.h"
00009 #include "filtermanager.h"
00010 #include "fourcc.h"
00011 #include "videodisplayprofile.h"
00012
00013 #include "mmsystem.h"
00014 #include "tv.h"
00015
00016 #undef UNICODE
00017
00018 extern "C" {
00019 #include "../libavcodec/avcodec.h"
00020 }
00021
00022 const int kNumBuffers = 31;
00023 const int kNeedFreeFrames = 1;
00024 const int kPrebufferFramesNormal = 12;
00025 const int kPrebufferFramesSmall = 4;
00026 const int kKeepPrebuffer = 2;
00027
00028
00029
00030
00031
00032
00033 #include <initguid.h>
00034 DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
00035 DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
00036 DEFINE_GUID( IID_IDirectDrawColorControl, 0x4B9F0EE0,0x0D7E,0x11D0,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8 );
00037
00038
00039 VideoOutputDX::VideoOutputDX(void)
00040 : VideoOutput(), XJ_width(0), XJ_height(0)
00041 {
00042 HMODULE user32;
00043
00044 XJ_started = 0;
00045
00046 pauseFrame.buf = NULL;
00047
00048 ddobject = NULL;
00049 display = NULL;
00050 display_driver = NULL;
00051
00052 clipper = NULL;
00053 ccontrol = NULL;
00054 wnd = NULL;
00055
00056
00057 using_overlay = true;
00058 overlay_3buf = true;
00059 use_sysmem = false;
00060
00061 front_surface = NULL;
00062 back_surface = NULL;
00063
00064
00065 monitor = NULL;
00066 display_driver = NULL;
00067 MonitorFromWindow = NULL;
00068 GetMonitorInfo = NULL;
00069 if ((user32 = GetModuleHandle("USER32")))
00070 {
00071 MonitorFromWindow = (HMONITOR (WINAPI*)(HWND, DWORD))
00072 GetProcAddress(user32, "MonitorFromWindow");
00073 GetMonitorInfo = (BOOL (WINAPI*)(HMONITOR, LPMONITORINFO))
00074 GetProcAddress(user32, "GetMonitorInfoA");
00075 }
00076 }
00077
00078 VideoOutputDX::~VideoOutputDX()
00079 {
00080 if (pauseFrame.buf)
00081 delete [] pauseFrame.buf;
00082
00083 DirectXCloseSurface();
00084 DirectXCloseDisplay();
00085 DirectXCloseDDraw();
00086
00087 Exit();
00088 }
00089
00090
00091 void VideoOutputDX::Zoom(ZoomDirection direction)
00092 {
00093 VideoOutput::Zoom(direction);
00094 MoveResize();
00095 }
00096
00097 void VideoOutputDX::MoveResize()
00098 {
00099 VideoOutput::MoveResize();
00100
00101 DirectXUpdateOverlay();
00102 }
00103
00104 bool VideoOutputDX::InputChanged(const QSize &input_size,
00105 float aspect,
00106 MythCodecID av_codec_id,
00107 void *codec_private)
00108 {
00109 VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private);
00110
00111 db_vdisp_profile->SetVideoRenderer("directx");
00112
00113 XJ_width = video_dim.width();
00114 XJ_height = video_dim.height();
00115
00116 vbuffers.DeleteBuffers();
00117
00118 DirectXCloseSurface();
00119 MakeSurface();
00120
00121 vbuffers.CreateBuffers(XJ_width, XJ_height);
00122
00123 MoveResize();
00124
00125 if (pauseFrame.buf)
00126 delete [] pauseFrame.buf;
00127
00128 pauseFrame.height = vbuffers.GetScratchFrame()->height;
00129 pauseFrame.width = vbuffers.GetScratchFrame()->width;
00130 pauseFrame.bpp = vbuffers.GetScratchFrame()->bpp;
00131 pauseFrame.size = vbuffers.GetScratchFrame()->size;
00132 pauseFrame.buf = new unsigned char[pauseFrame.size];
00133 pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00134
00135 return true;
00136 }
00137
00138 int VideoOutputDX::GetRefreshRate(void)
00139 {
00140 if (ddobject)
00141 {
00142 DWORD rate;
00143
00144 IDirectDraw_GetMonitorFrequency(ddobject, &rate);
00145
00146 return 1000000 / rate;
00147 }
00148
00149 return 0;
00150 }
00151
00152 void VideoOutputDX::WaitForVSync(void)
00153 {
00154 if (!ddobject)
00155 return;
00156
00157 IDirectDraw_WaitForVerticalBlank(ddobject, DDWAITVB_BLOCKBEGIN, NULL);
00158 }
00159
00160 bool VideoOutputDX::Init(int width, int height, float aspect,
00161 WId winid, int winx, int winy, int winw,
00162 int winh, WId embedid)
00163 {
00164 db_vdisp_profile->SetVideoRenderer("directx");
00165
00166 vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
00167 kPrebufferFramesNormal, kPrebufferFramesSmall,
00168 kKeepPrebuffer);
00169 VideoOutput::Init(width, height, aspect, winid,
00170 winx, winy, winw, winh, embedid);
00171
00172 wnd = winid;
00173
00174 XJ_width = video_dim.width();
00175 XJ_height = video_dim.height();
00176
00177 vbuffers.CreateBuffers(XJ_width, XJ_height);
00178 MoveResize();
00179
00180
00181
00182
00183 if (!ddobject && DirectXInitDDraw() != 0)
00184 {
00185 VERBOSE(VB_IMPORTANT, "cannot initialize DirectDraw");
00186 return false;
00187 }
00188
00189
00190 if (!display && DirectXCreateDisplay() != 0)
00191 {
00192 VERBOSE(VB_IMPORTANT, "cannot initialize DirectDraw");
00193 return false;
00194 }
00195
00196 MakeSurface();
00197
00198 if (!outputpictures)
00199 return false;
00200
00201 InitPictureAttributes();
00202
00203 MoveResize();
00204
00205 pauseFrame.height = vbuffers.GetScratchFrame()->height;
00206 pauseFrame.width = vbuffers.GetScratchFrame()->width;
00207 pauseFrame.bpp = vbuffers.GetScratchFrame()->bpp;
00208 pauseFrame.size = vbuffers.GetScratchFrame()->size;
00209 pauseFrame.buf = new unsigned char[pauseFrame.size];
00210 pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00211
00212 XJ_started = true;
00213
00214 return true;
00215 }
00216
00217 void VideoOutputDX::Exit(void)
00218 {
00219 if (XJ_started)
00220 {
00221 XJ_started = false;
00222
00223 vbuffers.DeleteBuffers();
00224 }
00225 }
00226
00227 void VideoOutputDX::EmbedInWidget(WId wid, int x, int y, int w,
00228 int h)
00229 {
00230 if (embedding)
00231 return;
00232
00233 VideoOutput::EmbedInWidget(wid, x, y, w, h);
00234 }
00235
00236 void VideoOutputDX::StopEmbedding(void)
00237 {
00238 if (!embedding)
00239 return;
00240
00241 VideoOutput::StopEmbedding();
00242 }
00243
00244 void VideoOutputDX::PrepareFrame(VideoFrame *buffer, FrameScanType t)
00245 {
00246 if (IsErrored())
00247 {
00248 VERBOSE(VB_IMPORTANT, "VideoOutputDX::PrepareFrame() called while IsErrored is true.");
00249 return;
00250 }
00251
00252 unsigned char *picbuf;
00253 int stride;
00254
00255 if (!buffer)
00256 buffer = vbuffers.GetScratchFrame();
00257
00258 framesPlayed = buffer->frameNumber + 1;
00259
00260 if (DirectXLockSurface((void**) &picbuf, &stride) == 0)
00261 {
00262 if (chroma == FOURCC_IYUV || chroma == FOURCC_I420)
00263 {
00264 for (int i = 0; i < XJ_height; i++)
00265 memcpy(picbuf + (i * stride), buffer->buf + (i * XJ_width), XJ_width);
00266 for (int i = 0; i < XJ_height / 2; i++)
00267 memcpy(picbuf + (XJ_height * stride) + (i * stride / 2),
00268 buffer->buf + XJ_height * XJ_width + (i * XJ_width / 2),
00269 XJ_width / 2);
00270 for (int i = 0; i < XJ_height / 2; i++)
00271 memcpy(picbuf + (XJ_height * stride * 5 / 4) + (i * stride / 2),
00272 buffer->buf + XJ_height * XJ_width * 5 / 4 + (i * XJ_width / 2),
00273 XJ_width / 2);
00274 }
00275 else if (chroma == FOURCC_YV12)
00276 {
00277 for (int i = 0; i < XJ_height; i++)
00278 memcpy(picbuf + (i * stride), buffer->buf + (i * XJ_width), XJ_width);
00279 for (int i = 0; i < XJ_height / 2; i++)
00280 memcpy(picbuf + (XJ_height * stride) + (i * stride / 2),
00281 buffer->buf + XJ_height * XJ_width * 5 / 4 + (i * XJ_width / 2),
00282 XJ_width / 2);
00283 for (int i = 0; i < XJ_height / 2; i++)
00284 memcpy(picbuf + (XJ_height * stride * 5 / 4) + (i * stride / 2),
00285 buffer->buf + XJ_height * XJ_width + (i * XJ_width / 2),
00286 XJ_width / 2);
00287 } else {
00288
00289 AVPicture image_in, image_out;
00290 int av_format;
00291
00292 switch (chroma)
00293 {
00294 case FOURCC_YUY2:
00295 case FOURCC_YUYV:
00296 case FOURCC_YUNV: av_format = PIX_FMT_YUV422; break;
00297 case FOURCC_RV15: av_format = PIX_FMT_RGB555; break;
00298 case FOURCC_RV16: av_format = PIX_FMT_RGB565; break;
00299 case FOURCC_RV24: av_format = PIX_FMT_RGB24; break;
00300 case FOURCC_RV32: av_format = PIX_FMT_RGBA32; break;
00301 default:
00302 VERBOSE(VB_IMPORTANT, "VODX: Non Xv mode only supports 16, 24, and 32 bpp displays");
00303 errored = true;
00304 return;
00305 }
00306
00307 avpicture_fill(&image_out, picbuf, av_format, XJ_width, XJ_height);
00308 image_out.linesize[0] = stride;
00309
00310 avpicture_fill(&image_in, buffer->buf, PIX_FMT_YUV420P, XJ_width, XJ_height);
00311
00312 img_convert(&image_out, av_format, &image_in, PIX_FMT_YUV420P, XJ_width, XJ_height);
00313
00314
00315 }
00316
00317 DirectXUnlockSurface();
00318 }
00319 else
00320 VERBOSE(VB_IMPORTANT, "Could not lock surface!");
00321 }
00322
00323 void VideoOutputDX::Show(FrameScanType )
00324 {
00325 HRESULT dxresult;
00326
00327 if (IsErrored())
00328 {
00329 VERBOSE(VB_IMPORTANT, "VideoOutputDX::Show() called while IsErrored istrue.");
00330 return;
00331 }
00332
00333 if ((display == NULL))
00334 {
00335 VERBOSE(VB_IMPORTANT, "no display!!");
00336 return;
00337 }
00338
00339
00340
00341 if (IDirectDrawSurface2_IsLost(display) == DDERR_SURFACELOST)
00342 {
00343 if (IDirectDrawSurface2_Restore(display) == DD_OK && using_overlay)
00344 DirectXUpdateOverlay();
00345 }
00346
00347 if (!using_overlay)
00348 {
00349 DDBLTFX ddbltfx;
00350 RECT rect_src;
00351 RECT rect_dest;
00352
00353 rect_src.left = video_rect.left();
00354 rect_src.right = XJ_width;
00355 rect_src.top = video_rect.top();
00356 rect_src.bottom = XJ_height;
00357
00358 if (display_video_rect.left() < display_visible_rect.left() ||
00359 display_video_rect.right() > display_visible_rect.right())
00360 {
00361 rect_dest.left = display_visible_rect.left();
00362 rect_dest.right = display_visible_rect.right();
00363
00364 int diff_x = display_visible_rect.left();
00365 diff_x -= display_video_rect.left();
00366 int diff_w = display_video_rect.width();
00367 diff_x -= display_visible_rect.width();
00368
00369 rect_src.left += (XJ_width * diff_x) / display_video_rect.width();
00370 rect_src.right -= ((XJ_width * (diff_w - diff_x)) /
00371 display_video_rect.width());
00372 }
00373 else
00374 {
00375 rect_dest.left = display_video_rect.left();
00376 rect_dest.right = display_video_rect.right();
00377 }
00378
00379 if (display_video_rect.top() < display_visible_rect.top() ||
00380 display_video_rect.bottom() > display_visible_rect.bottom())
00381 {
00382 rect_dest.top = display_visible_rect.top();
00383 rect_dest.bottom = display_visible_rect.bottom();
00384
00385 int diff_y = display_visible_rect.top();
00386 diff_y -= display_video_rect.top();
00387 int diff_h = display_video_rect.height();
00388 diff_h -= display_visible_rect.height();
00389
00390 rect_src.top += (XJ_height * diff_y) / display_video_rect.height();
00391 rect_src.bottom -= ((XJ_height * (diff_h - diff_y)) /
00392 display_video_rect.height());
00393 }
00394 else
00395 {
00396 rect_dest.top = display_video_rect.top();
00397 rect_dest.bottom = display_video_rect.bottom();
00398 }
00399
00400
00401 memset(&ddbltfx, 0, sizeof(DDBLTFX));
00402 ddbltfx.dwSize = sizeof(DDBLTFX);
00403 ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
00404
00405
00406 dxresult = IDirectDrawSurface2_Blt(display, &rect_dest, back_surface,
00407 &rect_src, DDBLT_ASYNC, &ddbltfx);
00408 if (dxresult != DD_OK)
00409 {
00410 VERBOSE(VB_IMPORTANT, "could not blit surface (error " << hex << dxresult << dec << ")");
00411 return;
00412 }
00413
00414 }
00415 else
00416 {
00417
00418 if (front_surface == back_surface)
00419 {
00420 return;
00421 }
00422
00423 dxresult = IDirectDrawSurface2_Flip(front_surface, NULL, DDFLIP_WAIT);
00424 if (dxresult != DD_OK)
00425 {
00426 VERBOSE(VB_IMPORTANT, "could not flip overlay (error " << hex << dxresult << dec << ")");
00427 }
00428
00429
00430
00431
00432 }
00433 }
00434
00435 void VideoOutputDX::DrawUnusedRects(bool)
00436 {
00437 }
00438
00439 void VideoOutputDX::UpdatePauseFrame(void)
00440 {
00441 VideoFrame *pauseb = vbuffers.GetScratchFrame();
00442 VideoFrame *pauseu = vbuffers.head(kVideoBuffer_used);
00443 if (pauseu)
00444 memcpy(pauseFrame.buf, pauseu->buf, pauseu->size);
00445 else
00446 memcpy(pauseFrame.buf, pauseb->buf, pauseb->size);
00447 }
00448
00449 void VideoOutputDX::ProcessFrame(VideoFrame *frame, OSD *osd,
00450 FilterChain *filterList,
00451 NuppelVideoPlayer *pipPlayer)
00452 {
00453 if (IsErrored())
00454 {
00455 VERBOSE(VB_IMPORTANT, "VideoOutputDX::ProcessFrame() called while IsErrored is true.");
00456 return;
00457 }
00458
00459 if (!frame)
00460 {
00461 frame = vbuffers.GetScratchFrame();
00462 CopyFrame(vbuffers.GetScratchFrame(), &pauseFrame);
00463 }
00464
00465 if (m_deinterlacing && m_deintFilter != NULL)
00466 m_deintFilter->ProcessFrame(frame);
00467 if (filterList)
00468 filterList->ProcessFrame(frame);
00469
00470 ShowPip(frame, pipPlayer);
00471 DisplayOSD(frame, osd);
00472 }
00473
00474
00475 int VideoOutputDX::SetPictureAttribute(
00476 PictureAttribute attribute, int newValue)
00477 {
00478 if (ccontrol == NULL)
00479 return -1;
00480
00481 newValue = min(max(newValue, 0), 100);
00482
00483 DDCOLORCONTROL ddcc;
00484 memset(&ddcc, 0, sizeof(DDCOLORCONTROL));
00485 ddcc.dwSize = sizeof(DDCOLORCONTROL);
00486
00487 switch (attribute)
00488 {
00489 case kPictureAttribute_Brightness:
00490 ddcc.dwFlags = DDCOLOR_BRIGHTNESS;
00491 ddcc.lBrightness = (newValue * newValue * 17) / 10 - 70 * newValue;
00492 break;
00493 case kPictureAttribute_Contrast:
00494 ddcc.dwFlags = DDCOLOR_CONTRAST;
00495 ddcc.lContrast = newValue * 200;
00496 break;
00497 case kPictureAttribute_Colour:
00498 ddcc.dwFlags = DDCOLOR_SATURATION;
00499 ddcc.lSaturation = newValue * 200;
00500 break;
00501 case kPictureAttribute_Hue:
00502 ddcc.dwFlags = DDCOLOR_HUE;
00503 ddcc.lHue = newValue * 36 / 10;
00504 if (ddcc.lHue > 180)
00505 ddcc.lHue -= 361;
00506 break;
00507 }
00508
00509 HRESULT dxresult;
00510
00511 dxresult = IDirectDrawColorControl_SetColorControls(ccontrol, &ddcc);
00512
00513 if (dxresult != DD_OK)
00514 {
00515 VERBOSE(VB_IMPORTANT, "Could not update colour controls: "
00516 << hex << dxresult << dec);
00517 return -1;
00518 }
00519
00520 SetPictureAttributeDBValue(attribute, newValue);
00521
00522 return newValue;
00523 }
00524
00525 float VideoOutputDX::GetDisplayAspect(void) const
00526 {
00527 float width = display_visible_rect.width();
00528 float height = display_visible_rect.height();
00529
00530 if (height <= 0.0001f)
00531 return 4.0f / 3.0f;
00532
00533 return width / height;
00534 }
00535
00536 static const DWORD pref_chromas[] = { FOURCC_IYUV,
00537 FOURCC_I420,
00538 FOURCC_YV12,
00539
00540
00541
00542 FOURCC_YUY2,
00543 FOURCC_YUYV,
00544 FOURCC_YUNV,
00545
00546 FOURCC_RGBX,
00547 0xFFFFFFFF };
00548
00549 void VideoOutputDX::MakeSurface()
00550 {
00551 outputpictures = 0;
00552
00553 if (using_overlay)
00554 {
00555 for (int i = 0; !outputpictures && (pref_chromas[i] != 0xFFFFFFFF); i++)
00556 {
00557 chroma = pref_chromas[i];
00558
00559 NewPicture();
00560 }
00561 }
00562
00563 if (!outputpictures)
00564 {
00565
00566 using_overlay = false;
00567 for (int i = 0; !outputpictures && (pref_chromas[i] != 0xFFFFFFFF); i++)
00568 {
00569 chroma = pref_chromas[i];
00570
00571 NewPicture();
00572 }
00573 }
00574
00575 if (!outputpictures)
00576 {
00577
00578 use_sysmem = true;
00579 for (int i = 0; !outputpictures && (pref_chromas[i] != 0xFFFFFFFF); i++)
00580 {
00581 chroma = pref_chromas[i];
00582
00583 NewPicture();
00584 }
00585 }
00586 }
00587
00588
00589
00590
00591 typedef HRESULT (WINAPI *LPFNDDC)(GUID *,LPDIRECTDRAW *,IUnknown *);
00592 typedef HRESULT (WINAPI *LPFNDDEE)(LPDDENUMCALLBACKEXA, LPVOID, DWORD);
00593
00594
00595
00596
00597
00598
00599
00600 int VideoOutputDX::DirectXInitDDraw()
00601 {
00602 HRESULT dxresult;
00603 LPFNDDC OurDirectDrawCreate;
00604 LPFNDDEE OurDirectDrawEnumerateEx;
00605 LPDIRECTDRAW p_ddobject;
00606
00607 VERBOSE(VB_IMPORTANT, "DirectXInitDDraw");
00608
00609
00610 ddraw_dll = LoadLibrary("DDRAW.DLL");
00611 if (ddraw_dll == NULL)
00612 {
00613 VERBOSE(VB_IMPORTANT, "DirectXInitDDraw failed loading ddraw.dll");
00614 goto error;
00615 }
00616
00617 OurDirectDrawCreate =
00618 (LPFNDDC)GetProcAddress(ddraw_dll, "DirectDrawCreate");
00619 if (OurDirectDrawCreate == NULL )
00620 {
00621 VERBOSE(VB_IMPORTANT, "DirectXInitDDraw failed GetProcAddress");
00622 goto error;
00623 }
00624
00625 OurDirectDrawEnumerateEx =
00626 (LPFNDDEE)GetProcAddress(ddraw_dll, "DirectDrawEnumerateExA");
00627
00628 if (OurDirectDrawEnumerateEx && MonitorFromWindow )
00629 {
00630 monitor = MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST);
00631
00632
00633
00634
00635 }
00636
00637
00638 dxresult = OurDirectDrawCreate(display_driver, &p_ddobject, NULL);
00639 if (dxresult != DD_OK)
00640 {
00641 VERBOSE(VB_IMPORTANT, "DirectXInitDDraw cannot initialize DDraw");
00642 goto error;
00643 }
00644
00645
00646 dxresult = IDirectDraw_QueryInterface(p_ddobject, IID_IDirectDraw2, (LPVOID *) &ddobject);
00647
00648 IDirectDraw_Release(p_ddobject);
00649 if (dxresult != DD_OK)
00650 {
00651 VERBOSE(VB_IMPORTANT, "cannot get IDirectDraw2 interface" );
00652 goto error;
00653 }
00654
00655
00656
00657 dxresult = IDirectDraw2_SetCooperativeLevel(ddobject, wnd, DDSCL_NORMAL);
00658 if (dxresult != DD_OK)
00659 {
00660 VERBOSE(VB_IMPORTANT, "cannot set direct draw cooperative level");
00661 goto error;
00662 }
00663
00664
00665 if (monitor && GetMonitorInfo)
00666 {
00667 MONITORINFO monitor_info;
00668 monitor_info.cbSize = sizeof(MONITORINFO);
00669 GetMonitorInfo(monitor, &monitor_info);
00670 rect_display = monitor_info.rcMonitor;
00671 }
00672 else
00673 {
00674 rect_display.left = 0;
00675 rect_display.top = 0;
00676 rect_display.right = GetSystemMetrics(SM_CXSCREEN);
00677 rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
00678 }
00679
00680 VERBOSE(VB_IMPORTANT, "screen dimensions ("
00681 << rect_display.left << "x"
00682 << rect_display.top << ","
00683 << rect_display.right << "x"
00684 << rect_display.bottom << ")");
00685
00686
00687 DirectXGetDDrawCaps();
00688
00689 VERBOSE(VB_IMPORTANT, "End DirectXInitDDraw");
00690 return 0;
00691
00692 error:
00693 if (ddobject)
00694 IDirectDraw2_Release(ddobject);
00695 if (ddraw_dll)
00696 FreeLibrary(ddraw_dll);
00697 ddraw_dll = NULL;
00698 ddobject = NULL;
00699 return -1;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 int VideoOutputDX::DirectXCreateClipper()
00711 {
00712 HRESULT dxresult;
00713
00714 VERBOSE(VB_IMPORTANT, "DirectXCreateClipper");
00715
00716
00717 dxresult = IDirectDraw2_CreateClipper(ddobject, 0, &clipper, NULL);
00718 if (dxresult != DD_OK)
00719 {
00720 VERBOSE(VB_IMPORTANT, "cannot create clipper (error " << hex << dxresult << dec << ")");
00721 goto error;
00722 }
00723
00724
00725 dxresult = IDirectDrawClipper_SetHWnd(clipper, 0, wnd);
00726 if (dxresult != DD_OK)
00727 {
00728 VERBOSE(VB_IMPORTANT, "cannot attach clipper to window (error " << hex << dxresult << dec << ")");
00729 goto error;
00730 }
00731
00732
00733 dxresult = IDirectDrawSurface_SetClipper(display, clipper);
00734 if (dxresult != DD_OK)
00735 {
00736 VERBOSE(VB_IMPORTANT, "cannot attach clipper to surface (error " << hex << dxresult << dec << ")");
00737 goto error;
00738 }
00739
00740 return 0;
00741
00742 error:
00743 if (clipper)
00744 {
00745 IDirectDrawClipper_Release(clipper);
00746 }
00747 clipper = NULL;
00748 return -1;
00749 }
00750
00751
00752
00753
00754
00755
00756
00757 int VideoOutputDX::DirectXCreateDisplay()
00758 {
00759 HRESULT dxresult;
00760 DDSURFACEDESC ddsd;
00761 LPDIRECTDRAWSURFACE p_display;
00762
00763 VERBOSE(VB_IMPORTANT, "DirectXCreateDisplay");
00764
00765
00766
00767 memset(&ddsd, 0, sizeof(DDSURFACEDESC));
00768 ddsd.dwSize = sizeof(DDSURFACEDESC);
00769 ddsd.dwFlags = DDSD_CAPS;
00770 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
00771
00772 dxresult = IDirectDraw2_CreateSurface(ddobject, &ddsd, &p_display, NULL );
00773 if (dxresult != DD_OK)
00774 {
00775 VERBOSE(VB_IMPORTANT, "cannot get primary surface (error %li)" << dxresult);
00776 return -1;
00777 }
00778
00779 dxresult = IDirectDrawSurface_QueryInterface(p_display, IID_IDirectDrawSurface2, (LPVOID *) &display);
00780
00781 IDirectDrawSurface_Release(p_display);
00782 if (dxresult != DD_OK)
00783 {
00784 VERBOSE(VB_IMPORTANT, "cannot query IDirectDrawSurface2 interface " <<
00785 "(error %li)" << dxresult);
00786 return -1;
00787 }
00788
00789
00790 DirectXCreateClipper();
00791
00792
00793 colorkey = 0;
00794 rgb_colorkey = DirectXFindColorkey(colorkey);
00795
00796 VERBOSE(VB_IMPORTANT, "colour key = " << hex << rgb_colorkey << dec);
00797
00798 VERBOSE(VB_IMPORTANT, "brushing");
00799
00800
00801 SetClassLong(wnd, GCL_HBRBACKGROUND,
00802 (LONG)CreateSolidBrush(rgb_colorkey));
00803 InvalidateRect(wnd, NULL, TRUE);
00804
00805
00806 VERBOSE(VB_IMPORTANT, "display created");
00807
00808 return 0;
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 int VideoOutputDX::DirectXCreateSurface(LPDIRECTDRAWSURFACE2 *pp_surface_final,
00822 DWORD i_chroma, bool b_overlay, int i_backbuffers)
00823 {
00824 HRESULT dxresult;
00825 LPDIRECTDRAWSURFACE p_surface;
00826 DDSURFACEDESC ddsd;
00827
00828
00829 if (b_overlay)
00830 {
00831
00832
00833
00834
00835
00836
00837
00838
00839 memset(&ddsd, 0, sizeof(DDSURFACEDESC));
00840 ddsd.dwSize = sizeof(DDSURFACEDESC);
00841 ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
00842 ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
00843 ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
00844 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
00845 ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
00846 ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
00847 ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP : 0);
00848 ddsd.dwHeight = XJ_height;
00849 ddsd.dwWidth = XJ_width;
00850 ddsd.dwBackBufferCount = i_backbuffers;
00851 }
00852 else
00853 {
00854 bool b_rgb_surface = (i_chroma == FOURCC_RGB2)
00855 || (i_chroma == FOURCC_RV15) || (i_chroma == FOURCC_RV16)
00856 || (i_chroma == FOURCC_RV24) || (i_chroma == FOURCC_RV32);
00857
00858 memset(&ddsd, 0, sizeof(DDSURFACEDESC));
00859 ddsd.dwSize = sizeof(DDSURFACEDESC);
00860 ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
00861 ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
00862 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
00863 ddsd.dwHeight = XJ_height;
00864 ddsd.dwWidth = XJ_width;
00865
00866 if (use_sysmem)
00867 ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
00868 else
00869 ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
00870
00871 if (!b_rgb_surface)
00872 {
00873 ddsd.dwFlags |= DDSD_PIXELFORMAT;
00874 ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
00875 ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
00876 }
00877 }
00878
00879 VERBOSE(VB_IMPORTANT, "VideoOutputDX::DirectXCreateSurface() x: "
00880 << XJ_width << " y: " << XJ_height
00881 << " chrom: " << fourcc_str(i_chroma));
00882
00883 dxresult = IDirectDraw2_CreateSurface(ddobject, &ddsd, &p_surface, NULL );
00884 if (dxresult != DD_OK )
00885 {
00886 VERBOSE(VB_IMPORTANT, "DD_CreateSurface failed " << hex << dxresult << dec);
00887 *pp_surface_final = NULL;
00888 return -1;
00889 }
00890
00891
00892 dxresult = IDirectDrawSurface_QueryInterface(p_surface, IID_IDirectDrawSurface2, (LPVOID *) pp_surface_final);
00893 IDirectDrawSurface_Release(p_surface);
00894 if (dxresult != DD_OK)
00895 {
00896 VERBOSE(VB_IMPORTANT, "cannot query IDirectDrawSurface2 interface " <<
00897 "(error " << hex << dxresult << dec << ")");
00898 *pp_surface_final = NULL;
00899 return -1;
00900 }
00901
00902 if (b_overlay)
00903 {
00904 back_surface = *pp_surface_final;
00905
00906
00907 char *picbuf;
00908 int stride;
00909
00910 if (DirectXLockSurface((void **) &picbuf, &stride) == DD_OK)
00911 {
00912 memset(picbuf, 127, stride * XJ_height * 3 / 2);
00913
00914 DirectXUnlockSurface();
00915 }
00916
00917 back_surface = NULL;
00918
00919
00920
00921 front_surface = *pp_surface_final;
00922 if (DirectXUpdateOverlay() != 0)
00923 {
00924 IDirectDrawSurface2_Release(*pp_surface_final);
00925 *pp_surface_final = NULL;
00926 front_surface = NULL;
00927 VERBOSE(VB_IMPORTANT, "overlay unuseable (might already be in use)" );
00928 return -1;
00929 }
00930 }
00931
00932
00933 dxresult = IDirectDraw_QueryInterface(*pp_surface_final, IID_IDirectDrawColorControl, (LPVOID *) &ccontrol);
00934 if (dxresult != DD_OK)
00935 {
00936 VERBOSE(VB_IMPORTANT, "cannot get colour control interface" );
00937 ccontrol = NULL;
00938 }
00939
00940 return 0;
00941 }
00942
00943
00944
00945
00946
00947
00948
00949 void VideoOutputDX::DirectXCloseDDraw()
00950 {
00951 VERBOSE(VB_IMPORTANT, "DirectXCloseDDraw");
00952 if (ddobject != NULL)
00953 {
00954 IDirectDraw2_Release(ddobject);
00955 ddobject = NULL;
00956 }
00957
00958 if (ddraw_dll != NULL)
00959 {
00960 FreeLibrary(ddraw_dll);
00961 ddraw_dll = NULL;
00962 }
00963
00964 if (display_driver != NULL)
00965 {
00966 free(display_driver);
00967 display_driver = NULL;
00968 }
00969
00970 monitor = NULL;
00971 }
00972
00973
00974
00975
00976
00977
00978 void VideoOutputDX::DirectXCloseDisplay()
00979 {
00980 VERBOSE(VB_IMPORTANT, "DirectXCloseDisplay");
00981
00982 if (clipper != NULL)
00983 {
00984 VERBOSE(VB_IMPORTANT, "DirectXCloseDisplay clipper");
00985 IDirectDrawClipper_Release(clipper);
00986 clipper = NULL;
00987 }
00988
00989 if (display != NULL)
00990 {
00991 VERBOSE(VB_IMPORTANT, "DirectXCloseDisplay display");
00992 IDirectDrawSurface2_Release(display);
00993 display = NULL;
00994 }
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 void VideoOutputDX::DirectXCloseSurface()
01004 {
01005 VERBOSE(VB_IMPORTANT, "DirectXCloseSurface");
01006
01007 if (ccontrol != NULL)
01008 {
01009 IDirectDrawColorControl_Release(ccontrol);
01010 ccontrol = NULL;
01011 }
01012
01013 if (front_surface != NULL)
01014 {
01015 IDirectDrawSurface2_Release(front_surface);
01016 front_surface = NULL;
01017 }
01018 }
01019
01020
01021
01022
01023
01024
01025
01026 int VideoOutputDX::NewPicture()
01027 {
01028 int i;
01029 int i_ret = -1;
01030 LPDIRECTDRAWSURFACE2 p_surface;
01031
01032 VERBOSE(VB_IMPORTANT, "NewPicture overlay");
01033
01034 outputpictures = 0;
01035
01036
01037 overlay_3buf = true;
01038
01039
01040
01041
01042
01043
01044
01045 if (using_overlay)
01046 {
01047
01048
01049
01050 if (overlay_3buf)
01051 i_ret = DirectXCreateSurface(&p_surface, chroma, using_overlay,
01052 2 );
01053
01054 if (!overlay_3buf || i_ret != 0)
01055 {
01056
01057 i_ret = DirectXCreateSurface(&p_surface, chroma, using_overlay,
01058 0 );
01059 }
01060
01061 if (i_ret == 0)
01062 {
01063 DDSCAPS dds_caps;
01064
01065
01066 front_surface = p_surface;
01067
01068
01069 memset(&dds_caps, 0, sizeof( DDSCAPS));
01070 dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
01071 if (DD_OK != IDirectDrawSurface2_GetAttachedSurface(p_surface, &dds_caps, &back_surface))
01072 {
01073 VERBOSE(VB_IMPORTANT, "NewPicture could not get back buffer");
01074
01075 back_surface = p_surface;
01076 }
01077
01078 DirectXUpdateOverlay();
01079 outputpictures = 1;
01080 VERBOSE(VB_IMPORTANT, "YUV overlay created successfully");
01081 }
01082 }
01083
01084
01085
01086
01087
01088
01089
01090 if (!using_overlay )
01091 {
01092 if (chroma != FOURCC_RGBX)
01093 {
01094 DWORD i_codes;
01095 DWORD *pi_codes;
01096 bool b_result = false;
01097
01098 bool is_rgb = ((chroma & 0xFF) == 'R');
01099
01100
01101
01102
01103 if (!is_rgb && IDirectDraw2_GetFourCCCodes(ddobject, &i_codes, NULL) == DD_OK)
01104 {
01105 pi_codes = (DWORD*) malloc(i_codes * sizeof(DWORD));
01106 if (pi_codes && IDirectDraw2_GetFourCCCodes(ddobject, &i_codes, pi_codes) == DD_OK)
01107 {
01108 for( i = 0; i < (int)i_codes; i++ )
01109 {
01110 if (chroma == pi_codes[i])
01111 {
01112 b_result = true;
01113 break;
01114 }
01115 }
01116 }
01117 }
01118
01119 if (is_rgb || b_result)
01120 i_ret = DirectXCreateSurface(&p_surface, chroma,
01121 0 ,
01122 0 );
01123 }
01124 else
01125 {
01126
01127 DDPIXELFORMAT ddpfPixelFormat;
01128
01129 ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01130 IDirectDrawSurface2_GetPixelFormat(display, &ddpfPixelFormat);
01131
01132 if (ddpfPixelFormat.dwFlags & DDPF_RGB)
01133 {
01134 switch(ddpfPixelFormat.dwRGBBitCount)
01135 {
01136
01137
01138
01139 case 15:
01140 chroma = FOURCC_RV15;
01141 break;
01142 case 16:
01143 chroma = FOURCC_RV16;
01144 break;
01145 case 24:
01146 chroma = FOURCC_RV24;
01147 break;
01148 case 32:
01149 chroma = FOURCC_RV32;
01150 break;
01151 default:
01152 VERBOSE(VB_IMPORTANT, "unknown screen depth");
01153 return 0;
01154 }
01155 }
01156
01157
01158
01159 i_ret = DirectXCreateSurface(&p_surface, chroma,
01160 0 ,
01161 0 );
01162
01163 }
01164
01165 if (i_ret == 0)
01166 {
01167
01168
01169 front_surface = back_surface = p_surface;
01170
01171 outputpictures = 1;
01172
01173 VERBOSE(VB_IMPORTANT, "created plain surface");
01174 }
01175 }
01176
01177 if (outputpictures) {
01178
01179
01180 if (DirectXLockSurface(NULL, NULL) != 0)
01181 {
01182
01183 outputpictures = 0;
01184 VERBOSE(VB_IMPORTANT, "cannot lock surface");
01185 return -1;
01186 }
01187 DirectXUnlockSurface();
01188 }
01189
01190 VERBOSE(VB_IMPORTANT, "End NewPictureVec (" <<
01191 (outputpictures ? "succeeded" : "failed") << ")");
01192
01193 return 0;
01194 }
01195
01196
01197
01198
01199
01200
01201
01202 void VideoOutputDX::DirectXGetDDrawCaps()
01203 {
01204 DDCAPS ddcaps;
01205 HRESULT dxresult;
01206
01207
01208
01209 memset(&ddcaps, 0, sizeof(DDCAPS));
01210 ddcaps.dwSize = sizeof(DDCAPS);
01211 dxresult = IDirectDraw2_GetCaps(ddobject, &ddcaps, NULL);
01212 if (dxresult != DD_OK )
01213 {
01214 VERBOSE(VB_IMPORTANT, "cannot get caps");
01215 }
01216 else
01217 {
01218 BOOL bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
01219 bHasColorKey, bCanStretch, bCanBltFourcc;
01220
01221
01222 bHasOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAY) ==
01223 DDCAPS_OVERLAY) ? TRUE : FALSE;
01224
01225 bHasOverlayFourCC = ((ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ==
01226 DDCAPS_OVERLAYFOURCC) ? TRUE : FALSE;
01227
01228 bCanDeinterlace = ((ddcaps.dwCaps & DDCAPS2_CANFLIPODDEVEN) ==
01229 0 ) ? TRUE : FALSE;
01230
01231 bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) ==
01232 DDCAPS_COLORKEY) ? TRUE : FALSE;
01233
01234 bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ==
01235 DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
01236
01237 bCanBltFourcc = ((ddcaps.dwCaps & DDCAPS_BLTFOURCC ) ==
01238 DDCAPS_BLTFOURCC) ? TRUE : FALSE;
01239
01240 VERBOSE(VB_IMPORTANT, "DirectDraw Capabilities: overlay=" << bHasOverlay
01241 << " yuvoverlay=" << bHasOverlayFourCC
01242 << " can_deinterlace_overlay=" << bCanDeinterlace
01243 << " colorkey=" << bHasColorKey
01244 << " stretch=" << bCanStretch
01245 << " bltfourcc=" << bCanBltFourcc);
01246
01247
01248
01249 }
01250 }
01251
01252
01253
01254
01255 DWORD VideoOutputDX::DirectXFindColorkey(uint32_t i_color)
01256 {
01257 DDSURFACEDESC ddsd;
01258 HRESULT dxresult;
01259 COLORREF i_rgb = 0;
01260 uint32_t i_pixel_backup;
01261 HDC hdc;
01262
01263 VERBOSE(VB_IMPORTANT, "determining colour key");
01264
01265 ddsd.dwSize = sizeof(ddsd);
01266 dxresult = IDirectDrawSurface2_Lock(display, NULL, &ddsd, DDLOCK_WAIT, NULL );
01267 if (dxresult != DD_OK)
01268 {
01269 VERBOSE(VB_IMPORTANT, "surface lock failed: 0x" << hex << dxresult << dec);
01270 return 0;
01271 }
01272
01273 VERBOSE(VB_IMPORTANT, "surface locked");
01274
01275 i_pixel_backup = *(uint32_t *)ddsd.lpSurface;
01276
01277 switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
01278 {
01279 case 4:
01280 *(uint8_t *)ddsd.lpSurface = i_color;
01281 break;
01282 case 8:
01283 *(uint8_t *)ddsd.lpSurface = i_color;
01284 break;
01285 case 16:
01286 *(uint16_t *)ddsd.lpSurface = i_color;
01287 break;
01288 default:
01289 *(uint32_t *)ddsd.lpSurface = i_color;
01290 break;
01291 }
01292
01293 IDirectDrawSurface2_Unlock(display, NULL);
01294
01295 VERBOSE(VB_IMPORTANT, "surface unlocked");
01296
01297 if (IDirectDrawSurface2_GetDC(display, &hdc) == DD_OK )
01298 {
01299 i_rgb = GetPixel(hdc, 0, 0);
01300 IDirectDrawSurface2_ReleaseDC(display, hdc);
01301 }
01302
01303 ddsd.dwSize = sizeof(ddsd);
01304 dxresult = IDirectDrawSurface2_Lock(display, NULL, &ddsd, DDLOCK_WAIT, NULL );
01305 if (dxresult != DD_OK )
01306 {
01307 VERBOSE(VB_IMPORTANT, "surface lock failed: 0x" << hex << dxresult << dec);
01308 return i_rgb;
01309 }
01310
01311 VERBOSE(VB_IMPORTANT, "surface locked");
01312
01313 *(uint32_t *)ddsd.lpSurface = i_pixel_backup;
01314
01315 IDirectDrawSurface2_Unlock(display, NULL);
01316
01317 VERBOSE(VB_IMPORTANT, "surface unlocked");
01318
01319 return i_rgb;
01320 }
01321
01322
01323
01324
01325
01326
01327
01328
01329 int VideoOutputDX::DirectXUpdateOverlay()
01330 {
01331 DDOVERLAYFX ddofx;
01332 DWORD dwFlags;
01333 HRESULT dxresult;
01334
01335
01336 RECT rect_src;
01337 RECT rect_dest;
01338
01339 if (front_surface == NULL || !using_overlay )
01340 return -1;
01341
01342
01343
01344
01345 rect_src.left = video_rect.left();
01346 rect_src.right = video_rect.right();
01347 rect_src.top = video_rect.top();
01348 rect_src.bottom = video_rect.bottom();
01349
01350 if (display_video_rect.left() < display_visible_rect.left() ||
01351 display_video_rect.right() > display_visible_rect.right())
01352 {
01353 rect_dest.left = display_visible_rect.left();
01354 rect_dest.right = display_visible_rect.right();
01355
01356 int diff_x = display_visible_rect.left();
01357 diff_x -= display_video_rect.left();
01358 int diff_w = display_video_rect.width();
01359 diff_x -= display_visible_rect.width();
01360
01361 rect_src.left += (XJ_width * diff_x) / display_video_rect.width();
01362 rect_src.right -= ((XJ_width * (diff_w - diff_x)) /
01363 display_video_rect.width());
01364 }
01365 else
01366 {
01367 rect_dest.left = display_video_rect.left();
01368 rect_dest.right = display_video_rect.right();
01369 }
01370
01371 if (display_video_rect.top() < display_visible_rect.top() ||
01372 display_video_rect.bottom() > display_visible_rect.bottom())
01373 {
01374 rect_dest.top = display_visible_rect.top();
01375 rect_dest.bottom = display_visible_rect.bottom();
01376
01377 int diff_y = display_visible_rect.top();
01378 diff_y -= display_video_rect.top();
01379 int diff_h = display_video_rect.height();
01380 diff_h -= display_visible_rect.height();
01381
01382 rect_src.top += ((video_rect.width() * diff_y) /
01383 display_video_rect.height());
01384
01385 rect_src.bottom -= (video_rect.height() * (diff_h - diff_y) /
01386 display_video_rect.height());
01387 }
01388 else
01389 {
01390 rect_dest.top = display_video_rect.top();
01391 rect_dest.bottom = display_video_rect.bottom();
01392 }
01393
01394 VERBOSE(VB_IMPORTANT, "rect_src ("
01395 << rect_src.left << "x"
01396 << rect_src.top << ","
01397 << rect_src.right << "x"
01398 << rect_src.bottom << ")");
01399
01400 VERBOSE(VB_IMPORTANT, "rect_dest ("
01401 << rect_dest.left << "x"
01402 << rect_dest.top << ","
01403 << rect_dest.right << "x"
01404 << rect_dest.bottom << ")");
01405
01406
01407
01408 memset(&ddofx, 0, sizeof(DDOVERLAYFX));
01409 ddofx.dwSize = sizeof(DDOVERLAYFX);
01410 ddofx.dckDestColorkey.dwColorSpaceLowValue = colorkey;
01411 ddofx.dckDestColorkey.dwColorSpaceHighValue = colorkey;
01412
01413 dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
01414
01415 dxresult = IDirectDrawSurface2_UpdateOverlay(front_surface,
01416 &rect_src,
01417 display,
01418 &rect_dest,
01419 dwFlags, &ddofx );
01420 if (dxresult != DD_OK)
01421 {
01422 VERBOSE(VB_IMPORTANT,
01423 "DirectXUpdateOverlay cannot move or resize overlay: " << hex << dxresult << dec);
01424 return -1;
01425 }
01426
01427 return 0;
01428 }
01429
01430
01431
01432
01433
01434
01435
01436 int VideoOutputDX::DirectXLockSurface(void **picbuf, int *stride)
01437 {
01438 HRESULT dxresult;
01439 DDSURFACEDESC ddsd;
01440
01441
01442 memset(&ddsd, 0, sizeof(DDSURFACEDESC));
01443 ddsd.dwSize = sizeof(DDSURFACEDESC);
01444 dxresult = IDirectDrawSurface2_Lock(back_surface,
01445 NULL, &ddsd,
01446 DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
01447 NULL );
01448 if (dxresult != DD_OK)
01449 {
01450 if (dxresult == DDERR_INVALIDPARAMS)
01451 {
01452
01453
01454 dxresult = IDirectDrawSurface2_Lock(back_surface, NULL,
01455 &ddsd,
01456 DDLOCK_WAIT, NULL);
01457 }
01458 if (dxresult == DDERR_SURFACELOST)
01459 {
01460
01461
01462
01463
01464
01465 if (using_overlay )
01466 IDirectDrawSurface2_Restore(front_surface);
01467 else
01468 IDirectDrawSurface2_Restore(back_surface);
01469
01470 dxresult = IDirectDrawSurface2_Lock(back_surface, NULL,
01471 &ddsd,
01472 DDLOCK_WAIT, NULL);
01473 if (dxresult == DDERR_SURFACELOST)
01474 VERBOSE(VB_IMPORTANT, "DirectXLockSurface: DDERR_SURFACELOST");
01475 }
01476 if (dxresult != DD_OK)
01477 {
01478 return -1;
01479 }
01480 }
01481
01482 if (picbuf)
01483 *picbuf = ddsd.lpSurface;
01484
01485 if (stride)
01486 *stride = ddsd.lPitch;
01487
01488 return 0;
01489 }
01490
01491
01492
01493
01494 int VideoOutputDX::DirectXUnlockSurface()
01495 {
01496
01497 if (IDirectDrawSurface2_Unlock(back_surface, NULL) == DD_OK)
01498 return 0;
01499 else
01500 return -1;
01501 }
01502
01503 QStringList VideoOutputDX::GetAllowedRenderers(
01504 MythCodecID myth_codec_id, const QSize &video_dim)
01505 {
01506 QStringList list;
01507 list += "directx";
01508 return list;
01509 }
01510