void renderer_dd::ddraw_delete() { // free surfaces ddraw_delete_surfaces(); // restore resolutions if (ddraw != NULL) IDirectDraw7_RestoreDisplayMode(ddraw); // reset cooperative level if (ddraw != NULL && window().m_hwnd != NULL) IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_NORMAL); // release the DirectDraw object itself if (ddraw != NULL) IDirectDraw7_Release(ddraw); ddraw = NULL; }
static void ddraw_delete(win_window_info *window) { dd_info *dd = window->drawdata; // free surfaces ddraw_delete_surfaces(window); // restore resolutions if (dd->ddraw != NULL) IDirectDraw7_RestoreDisplayMode(dd->ddraw); // reset cooperative level if (dd->ddraw != NULL && window->hwnd != NULL) IDirectDraw7_SetCooperativeLevel(dd->ddraw, window->hwnd, DDSCL_NORMAL); // release the DirectDraw object itself if (dd->ddraw != NULL) IDirectDraw7_Release(dd->ddraw); dd->ddraw = NULL; }
int renderer_dd::ddraw_test_cooperative() { HRESULT result; // check our current status; if we lost the device, punt to GDI result = IDirectDraw7_TestCooperativeLevel(ddraw); switch (result) { // punt to GDI if someone else has exclusive mode case DDERR_NOEXCLUSIVEMODE: case DDERR_EXCLUSIVEMODEALREADYSET: ddraw_delete_surfaces(); return 1; // if we're ok, but we don't have a primary surface, create one default: case DD_OK: if (primary == NULL) return ddraw_create_surfaces(); return 0; } }
static int ddraw_test_cooperative(win_window_info *window) { dd_info *dd = (dd_info *)window->drawdata; HRESULT result; // check our current status; if we lost the device, punt to GDI result = IDirectDraw7_TestCooperativeLevel(dd->ddraw); switch (result) { // punt to GDI if someone else has exclusive mode case DDERR_NOEXCLUSIVEMODE: case DDERR_EXCLUSIVEMODEALREADYSET: ddraw_delete_surfaces(window); return 1; // if we're ok, but we don't have a primary surface, create one default: case DD_OK: if (dd->primary == NULL) return ddraw_create_surfaces(window); return 0; } }
static int ddraw_create_surfaces(win_window_info *window) { dd_info *dd = window->drawdata; HRESULT result; // make a description of the primary surface memset(&dd->primarydesc, 0, sizeof(dd->primarydesc)); dd->primarydesc.dwSize = sizeof(dd->primarydesc); dd->primarydesc.dwFlags = DDSD_CAPS; dd->primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // for triple-buffered full screen mode, allocate flipping surfaces if (window->fullscreen && video_config.triplebuf) { dd->primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; dd->primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; dd->primarydesc.dwBackBufferCount = 2; } // create the primary surface and report errors result = create_surface(dd, &dd->primarydesc, &dd->primary, "primary"); if (result != DD_OK) goto error; // full screen mode: get the back surface dd->back = NULL; if (window->fullscreen && video_config.triplebuf) { DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; result = IDirectDrawSurface7_GetAttachedSurface(dd->primary, &caps, &dd->back); if (result != DD_OK) { mame_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result); goto error; } } // now make a description of our blit surface, based on the primary surface if (dd->blitwidth == 0 || dd->blitheight == 0) compute_blit_surface_size(window); dd->blitdesc = dd->primarydesc; dd->blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; dd->blitdesc.dwWidth = dd->blitwidth; dd->blitdesc.dwHeight = dd->blitheight; dd->blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; // then create the blit surface, fall back to system memory if video mem doesn't work result = create_surface(dd, &dd->blitdesc, &dd->blit, "blit"); if (result != DD_OK) { dd->blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; result = create_surface(dd, &dd->blitdesc, &dd->blit, "blit"); } if (result != DD_OK) goto error; // create a memory buffer for offscreen drawing if (dd->membuffersize < dd->blitwidth * dd->blitheight * 4) { dd->membuffersize = dd->blitwidth * dd->blitheight * 4; dd->membuffer = realloc(dd->membuffer, dd->membuffersize); } if (dd->membuffer == NULL) goto error; #ifdef MESS // create a clipper for all modes, since MESS has dialogs if (create_clipper(window)) goto error; #else // create a clipper for windowed mode if (!window->fullscreen && create_clipper(window)) goto error; #endif // full screen mode: set the gamma if (window->fullscreen) { // only set the gamma if it's not 1.0f float brightness = options_get_float(mame_options(), WINOPTION_FULLSCREENBRIGHTNESS); float contrast = options_get_float(mame_options(), WINOPTION_FULLLSCREENCONTRAST); float gamma = options_get_float(mame_options(), WINOPTION_FULLSCREENGAMMA); if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f) { // see if we can get a GammaControl object result = IDirectDrawSurface_QueryInterface(dd->primary, &IID_IDirectDrawGammaControl, (void **)&dd->gamma); if (result != DD_OK) { mame_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n"); dd->gamma = NULL; } // proceed if we can if (dd->gamma != NULL) { DDGAMMARAMP ramp; int i; // create a standard ramp and set it for (i = 0; i < 256; i++) ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8; // attempt to set it result = IDirectDrawGammaControl_SetGammaRamp(dd->gamma, 0, &ramp); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result); } } } // force some updates update_outer_rects(dd); return 0; error: ddraw_delete_surfaces(window); return 1; }
static int drawdd_window_draw(win_window_info *window, HDC dc, int update) { dd_info *dd = window->drawdata; const render_primitive *prim; int usemembuffer = FALSE; HRESULT result; // if we haven't been created, just punt if (dd == NULL) return 1; // if we're updating, remember to erase the outer stuff if (update) update_outer_rects(dd); // if we have a ddraw object, check the cooperative level if (ddraw_test_cooperative(window)) return 1; // get the size; if we're too small, delete the existing surfaces if (dd->blitwidth > dd->blitdesc.dwWidth || dd->blitheight > dd->blitdesc.dwHeight) ddraw_delete_surfaces(window); // if we need to create surfaces, do it now if (dd->blit == NULL && ddraw_create_surfaces(window) != 0) return 1; // select our surface and lock it result = IDirectDrawSurface7_Lock(dd->blit, NULL, &dd->blitdesc, DDLOCK_WAIT, NULL); if (result == DDERR_SURFACELOST) { mame_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n"); ddraw_delete_surfaces(window); return 1; } if (result != DD_OK) { mame_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result); return 1; } // render to it osd_lock_acquire(window->primlist->lock); // scan the list of primitives for tricky stuff for (prim = window->primlist->head; prim != NULL; prim = prim->next) if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE || (prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32)) { usemembuffer = TRUE; break; } // if we're using the memory buffer, draw offscreen first and then copy if (usemembuffer) { int x, y; // based on the target format, use one of our standard renderers switch (dd->blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: drawdd_rgb888_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; case 0x000000ff: drawdd_bgr888_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; case 0xf800: drawdd_rgb565_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; case 0x7c00: drawdd_rgb555_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; default: mame_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)dd->blitdesc.ddpfPixelFormat.dwRBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwGBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwBBitMask); break; } // handle copying to both 16bpp and 32bpp destinations for (y = 0; y < dd->blitheight; y++) { if (dd->blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) { UINT32 *src = (UINT32 *)dd->membuffer + y * dd->blitwidth; UINT32 *dst = (UINT32 *)((UINT8 *)dd->blitdesc.lpSurface + y * dd->blitdesc.lPitch); for (x = 0; x < dd->blitwidth; x++) *dst++ = *src++; } else if (dd->blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) { UINT16 *src = (UINT16 *)dd->membuffer + y * dd->blitwidth; UINT16 *dst = (UINT16 *)((UINT8 *)dd->blitdesc.lpSurface + y * dd->blitdesc.lPitch); for (x = 0; x < dd->blitwidth; x++) *dst++ = *src++; } } } // otherwise, draw directly else { // based on the target format, use one of our standard renderers switch (dd->blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: drawdd_rgb888_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 4); break; case 0x000000ff: drawdd_bgr888_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 4); break; case 0xf800: drawdd_rgb565_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 2); break; case 0x7c00: drawdd_rgb555_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 2); break; default: mame_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)dd->blitdesc.ddpfPixelFormat.dwRBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwGBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwBBitMask); break; } } osd_lock_release(window->primlist->lock); // unlock and blit result = IDirectDrawSurface7_Unlock(dd->blit, NULL); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result); // sync to VBLANK if ((video_config.waitvsync || video_config.syncrefresh) && video_get_throttle() && (!window->fullscreen || dd->back == NULL)) { result = IDirectDraw7_WaitForVerticalBlank(dd->ddraw, DDWAITVB_BLOCKBEGIN, NULL); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); } // complete the blitting blit_to_primary(window, dd->blitwidth, dd->blitheight); return 0; }
int renderer_dd::ddraw_create_surfaces() { HRESULT result; // make a description of the primary surface memset(&primarydesc, 0, sizeof(primarydesc)); primarydesc.dwSize = sizeof(primarydesc); primarydesc.dwFlags = DDSD_CAPS; primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // for triple-buffered full screen mode, allocate flipping surfaces if (window().fullscreen() && video_config.triplebuf) { primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; primarydesc.dwBackBufferCount = 2; } // create the primary surface and report errors result = create_surface(&primarydesc, &primary, "primary"); if (result != DD_OK) goto error; // full screen mode: get the back surface back = NULL; if (window().fullscreen() && video_config.triplebuf) { DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; result = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &back); if (result != DD_OK) { osd_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result); goto error; } } // now make a description of our blit surface, based on the primary surface if (blitwidth == 0 || blitheight == 0) compute_blit_surface_size(); blitdesc = primarydesc; blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; blitdesc.dwWidth = blitwidth; blitdesc.dwHeight = blitheight; blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; // then create the blit surface, fall back to system memory if video mem doesn't work result = create_surface(&blitdesc, &blit, "blit"); if (result != DD_OK) { blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; result = create_surface(&blitdesc, &blit, "blit"); } if (result != DD_OK) goto error; // create a memory buffer for offscreen drawing if (membuffersize < blitwidth * blitheight * 4) { membuffersize = blitwidth * blitheight * 4; global_free_array(membuffer); membuffer = global_alloc_array_nothrow(UINT8, membuffersize); } if (membuffer == NULL) goto error; // create a clipper for windowed mode if (!window().fullscreen() && create_clipper()) goto error; // full screen mode: set the gamma if (window().fullscreen()) { // only set the gamma if it's not 1.0f windows_options &options = downcast<windows_options &>(window().machine().options()); float brightness = options.full_screen_brightness(); float contrast = options.full_screen_contrast(); float fgamma = options.full_screen_gamma(); if (brightness != 1.0f || contrast != 1.0f || fgamma != 1.0f) { // see if we can get a GammaControl object result = IDirectDrawSurface_QueryInterface(primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&gamma); if (result != DD_OK) { osd_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n"); this->gamma = NULL; } // proceed if we can if (this->gamma != NULL) { DDGAMMARAMP ramp; int i; // create a standard ramp and set it for (i = 0; i < 256; i++) ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, fgamma) << 8; // attempt to set it result = IDirectDrawGammaControl_SetGammaRamp(this->gamma, 0, &ramp); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result); } } } // force some updates update_outer_rects(); return 0; error: ddraw_delete_surfaces(); return 1; }
int renderer_dd::draw(const int update) { render_primitive *prim; int usemembuffer = FALSE; HRESULT result; // if we're updating, remember to erase the outer stuff if (update) update_outer_rects(); // if we have a ddraw object, check the cooperative level if (ddraw_test_cooperative()) return 1; // get the size; if we're too small, delete the existing surfaces if (blitwidth > blitdesc.dwWidth || blitheight > blitdesc.dwHeight) ddraw_delete_surfaces(); // if we need to create surfaces, do it now if (blit == NULL && ddraw_create_surfaces() != 0) return 1; // select our surface and lock it result = IDirectDrawSurface7_Lock(blit, NULL, &blitdesc, DDLOCK_WAIT, NULL); if (result == DDERR_SURFACELOST) { osd_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n"); ddraw_delete_surfaces(); return 1; } if (result != DD_OK) { osd_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result); return 1; } // render to it window().m_primlist->acquire_lock(); // scan the list of primitives for tricky stuff for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE || (prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32)) { usemembuffer = TRUE; break; } // if we're using the memory buffer, draw offscreen first and then copy if (usemembuffer) { int x, y; // based on the target format, use one of our standard renderers switch (blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; default: osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); break; } // handle copying to both 16bpp and 32bpp destinations for (y = 0; y < blitheight; y++) { if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) { UINT32 *src = (UINT32 *)membuffer + y * blitwidth; UINT32 *dst = (UINT32 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); for (x = 0; x < blitwidth; x++) *dst++ = *src++; } else if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) { UINT16 *src = (UINT16 *)membuffer + y * blitwidth; UINT16 *dst = (UINT16 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); for (x = 0; x < blitwidth; x++) *dst++ = *src++; } } } // otherwise, draw directly else { // based on the target format, use one of our standard renderers switch (blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; default: osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); break; } } window().m_primlist->release_lock(); // unlock and blit result = IDirectDrawSurface7_Unlock(blit, NULL); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result); // sync to VBLANK if ((video_config.waitvsync || video_config.syncrefresh) && window().machine().video().throttled() && (!window().fullscreen() || back == NULL)) { result = IDirectDraw7_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKBEGIN, NULL); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); } // complete the blitting blit_to_primary(blitwidth, blitheight); return 0; }