/** * It allocates and initializes the resources needed to render the scene. */ static int Direct3DCreateScene(vout_display_t *vd, const video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev; HRESULT hr; /* * Create a texture for use when rendering a scene * for performance reason, texture format is identical to backbuffer * which would usually be a RGB format */ LPDIRECT3DTEXTURE9 d3dtex; hr = IDirect3DDevice9_CreateTexture(d3ddev, fmt->i_width, fmt->i_height, 1, D3DUSAGE_RENDERTARGET, sys->d3dpp.BackBufferFormat, D3DPOOL_DEFAULT, &d3dtex, NULL); if (FAILED(hr)) { msg_Err(vd, "Failed to create texture. (hr=0x%lx)", hr); return VLC_EGENERIC; } /* ** Create a vertex buffer for use when rendering scene */ LPDIRECT3DVERTEXBUFFER9 d3dvtc; hr = IDirect3DDevice9_CreateVertexBuffer(d3ddev, sizeof(CUSTOMVERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &d3dvtc, NULL); if (FAILED(hr)) { msg_Err(vd, "Failed to create vertex buffer. (hr=0x%lx)", hr); IDirect3DTexture9_Release(d3dtex); return VLC_EGENERIC; } /* */ sys->d3dtex = d3dtex; sys->d3dvtc = d3dvtc; sys->d3dregion_count = 0; sys->d3dregion = NULL; sys->clear_scene = true; // Texture coordinates outside the range [0.0, 1.0] are set // to the texture color at 0.0 or 1.0, respectively. IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // Set linear filtering quality if (sys->d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) { msg_Dbg(vd, "Using D3DTEXF_LINEAR for minification"); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); } else { msg_Dbg(vd, "Using D3DTEXF_POINT for minification"); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT); } if (sys->d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) { msg_Dbg(vd, "Using D3DTEXF_LINEAR for magnification"); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); } else { msg_Dbg(vd, "Using D3DTEXF_POINT for magnification"); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); } // set maximum ambient light IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255)); // Turn off culling IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_CULLMODE, D3DCULL_NONE); // Turn off the zbuffer IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ZENABLE, D3DZB_FALSE); // Turn off lights IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_LIGHTING, FALSE); // Enable dithering IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_DITHERENABLE, TRUE); // disable stencil IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_STENCILENABLE, FALSE); // manage blending IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, FALSE); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); if (sys->d3dcaps.AlphaCmpCaps & D3DPCMPCAPS_GREATER) { IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHATESTENABLE,TRUE); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHAREF, 0x00); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHAFUNC,D3DCMP_GREATER); } // Set texture states IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLOROP,D3DTOP_SELECTARG1); IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG1,D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAARG1,D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); msg_Dbg(vd, "Direct3D scene created successfully"); return VLC_SUCCESS; }
static int _al_draw_prim_raw(ALLEGRO_BITMAP* texture, const void* vtx, const ALLEGRO_VERTEX_DECL* decl, const int* indices, int num_vtx, int type) { int stride = decl ? decl->stride : (int)sizeof(ALLEGRO_VERTEX); int num_primitives = 0; ALLEGRO_DISPLAY *display; LPDIRECT3DDEVICE9 device; LPDIRECT3DBASETEXTURE9 d3d_texture; DWORD old_wrap_state[2]; DWORD old_ttf_state; int min_idx = 0, max_idx = num_vtx - 1; if(indices) { int ii; for(ii = 0; ii < num_vtx; ii++) { int idx = indices[ii]; if(ii == 0) { min_idx = idx; max_idx = idx; } else if (idx < min_idx) { min_idx = idx; } else if (idx > max_idx) { max_idx = idx; } } } display = al_get_current_display(); device = al_d3d_get_device(display); if(decl) { if(decl->d3d_decl) { IDirect3DDevice9_SetVertexDeclaration(device, (IDirect3DVertexDeclaration9*)decl->d3d_decl); } else { return _al_draw_prim_soft(texture, vtx, decl, 0, num_vtx, type); } } else { IDirect3DDevice9_SetFVF(device, A5V_FVF); } set_blender(display); if (texture) { int tex_x, tex_y; D3DSURFACE_DESC desc; float mat[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; IDirect3DTexture9_GetLevelDesc(al_d3d_get_video_texture(texture), 0, &desc); al_get_d3d_texture_position(texture, &tex_x, &tex_y); if(decl) { if(decl->elements[ALLEGRO_PRIM_TEX_COORD_PIXEL].attribute) { mat[0][0] = 1.0f / desc.Width; mat[1][1] = 1.0f / desc.Height; } else { mat[0][0] = (float)al_get_bitmap_width(texture) / desc.Width; mat[1][1] = (float)al_get_bitmap_height(texture) / desc.Height; } } else { mat[0][0] = 1.0f / desc.Width; mat[1][1] = 1.0f / desc.Height; } mat[2][0] = (float)tex_x / desc.Width; mat[2][1] = (float)tex_y / desc.Height; IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, &old_ttf_state); IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *)&mat); d3d_texture = (LPDIRECT3DBASETEXTURE9)al_d3d_get_video_texture(texture); IDirect3DDevice9_SetTexture(device, 0, d3d_texture); } else { IDirect3DDevice9_SetTexture(device, 0, NULL); } IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_ADDRESSU, &old_wrap_state[0]); IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_ADDRESSV, &old_wrap_state[1]); IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); if(!indices) { switch (type) { case ALLEGRO_PRIM_LINE_LIST: { num_primitives = num_vtx / 2; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_LINELIST, num_primitives, vtx, stride); break; }; case ALLEGRO_PRIM_LINE_STRIP: { num_primitives = num_vtx - 1; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_LINESTRIP, num_primitives, vtx, stride); break; }; case ALLEGRO_PRIM_LINE_LOOP: { int in[2]; in[0] = 0; in[1] = num_vtx-1; num_primitives = num_vtx - 1; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_LINESTRIP, num_primitives, vtx, stride); IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_LINELIST, 0, num_vtx, 1, in, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_TRIANGLE_LIST: { num_primitives = num_vtx / 3; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, num_primitives, vtx, stride); break; }; case ALLEGRO_PRIM_TRIANGLE_STRIP: { num_primitives = num_vtx - 2; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, num_primitives, vtx, stride); break; }; case ALLEGRO_PRIM_TRIANGLE_FAN: { num_primitives = num_vtx - 2; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, num_primitives, vtx, stride); break; }; case ALLEGRO_PRIM_POINT_LIST: { num_primitives = num_vtx; IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, num_primitives, vtx, stride); break; }; } } else { switch (type) { case ALLEGRO_PRIM_LINE_LIST: { num_primitives = num_vtx / 2; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_LINELIST, min_idx, max_idx + 1, num_primitives, indices, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_LINE_STRIP: { num_primitives = num_vtx - 1; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_LINESTRIP, min_idx, max_idx + 1, num_primitives, indices, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_LINE_LOOP: { int in[2]; num_primitives = num_vtx - 1; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_LINESTRIP, min_idx, max_idx + 1, num_primitives, indices, D3DFMT_INDEX32, vtx, stride); in[0] = indices[0]; in[1] = indices[num_vtx-1]; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_LINELIST, min_idx, max_idx + 1, 1, in, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_TRIANGLE_LIST: { num_primitives = num_vtx / 3; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, min_idx, max_idx + 1, num_primitives, indices, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_TRIANGLE_STRIP: { num_primitives = num_vtx - 2; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLESTRIP, min_idx, max_idx + 1, num_primitives, indices, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_TRIANGLE_FAN: { num_primitives = num_vtx - 2; IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLEFAN, min_idx, max_idx + 1, num_primitives, indices, D3DFMT_INDEX32, vtx, stride); break; }; case ALLEGRO_PRIM_POINT_LIST: { /* * D3D does not support point lists in indexed mode, so we draw them using the non-indexed mode. To gain at least a semblance * of speed, we detect consecutive runs of vertices and draw them using a single DrawPrimitiveUP call */ int ii = 0; int start_idx = indices[0]; int run_length = 0; for(ii = 0; ii < num_vtx; ii++) { run_length++; if(indices[ii] + 1 != indices[ii + 1] || ii == num_vtx - 1) { IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, run_length, (const char*)vtx + start_idx * stride, stride); if(ii != num_vtx - 1) start_idx = indices[ii + 1]; run_length = 0; } } break; }; } } IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, old_wrap_state[0]); IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, old_wrap_state[1]); if(texture) { IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, old_ttf_state); } return num_primitives; }
SDL_Renderer * D3D_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_Renderer *renderer; D3D_RenderData *data; SDL_SysWMinfo windowinfo; HRESULT result; D3DPRESENT_PARAMETERS pparams; IDirect3DSwapChain9 *chain; D3DCAPS9 caps; Uint32 window_flags; int w, h; SDL_DisplayMode fullscreen_mode; D3DMATRIX matrix; int d3dxVersion; char d3dxDLLFile[50]; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); SDL_OutOfMemory(); return NULL; } data->d3dDLL = SDL_LoadObject("D3D9.DLL"); if (data->d3dDLL) { IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion); D3DCreate = (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL, "Direct3DCreate9"); if (D3DCreate) { data->d3d = D3DCreate(D3D_SDK_VERSION); } if (!data->d3d) { SDL_UnloadObject(data->d3dDLL); data->d3dDLL = NULL; } for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) { LPTSTR dllName; SDL_snprintf(d3dxDLLFile, sizeof(d3dxDLLFile), "D3DX9_%02d.dll", d3dxVersion); dllName = WIN_UTF8ToString(d3dxDLLFile); data->d3dxDLL = (void *)LoadLibrary(dllName); /* not using SDL_LoadObject() as we want silently fail - no error message */ SDL_free(dllName); if (data->d3dxDLL) { HRESULT (WINAPI *D3DXCreateMatrixStack) (DWORD Flags, LPD3DXMATRIXSTACK* ppStack); D3DXCreateMatrixStack = (HRESULT (WINAPI *) (DWORD, LPD3DXMATRIXSTACK*)) SDL_LoadFunction(data->d3dxDLL, "D3DXCreateMatrixStack"); if (D3DXCreateMatrixStack) { D3DXCreateMatrixStack(0, &data->matrixStack); break; } } } if (!data->matrixStack) { if (data->d3dxDLL) SDL_UnloadObject(data->d3dxDLL); } } if (!data->d3d || !data->matrixStack) { SDL_free(renderer); SDL_free(data); SDL_SetError("Unable to create Direct3D interface"); return NULL; } renderer->WindowEvent = D3D_WindowEvent; renderer->CreateTexture = D3D_CreateTexture; renderer->UpdateTexture = D3D_UpdateTexture; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; renderer->SetRenderTarget = D3D_SetRenderTarget; renderer->UpdateViewport = D3D_UpdateViewport; renderer->UpdateClipRect = D3D_UpdateClipRect; renderer->RenderClear = D3D_RenderClear; renderer->RenderDrawPoints = D3D_RenderDrawPoints; renderer->RenderDrawLines = D3D_RenderDrawLines; renderer->RenderFillRects = D3D_RenderFillRects; renderer->RenderCopy = D3D_RenderCopy; renderer->RenderCopyEx = D3D_RenderCopyEx; renderer->RenderReadPixels = D3D_RenderReadPixels; renderer->RenderPresent = D3D_RenderPresent; renderer->DestroyTexture = D3D_DestroyTexture; renderer->DestroyRenderer = D3D_DestroyRenderer; renderer->info = D3D_RenderDriver.info; renderer->driverdata = data; renderer->info.flags = SDL_RENDERER_ACCELERATED; SDL_VERSION(&windowinfo.version); SDL_GetWindowWMInfo(window, &windowinfo); window_flags = SDL_GetWindowFlags(window); SDL_GetWindowSize(window, &w, &h); SDL_GetWindowDisplayMode(window, &fullscreen_mode); SDL_zero(pparams); pparams.hDeviceWindow = windowinfo.info.win.window; pparams.BackBufferWidth = w; pparams.BackBufferHeight = h; if (window_flags & SDL_WINDOW_FULLSCREEN) { pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format); } else { pparams.BackBufferFormat = D3DFMT_UNKNOWN; } pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; if (window_flags & SDL_WINDOW_FULLSCREEN) { if ( ( window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP ) { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; } else { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; } } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; } if (flags & SDL_RENDERER_PRESENTVSYNC) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } /* FIXME: Which adapter? */ data->adapter = D3DADAPTER_DEFAULT; IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps); result = IDirect3D9_CreateDevice(data->d3d, data->adapter, D3DDEVTYPE_HAL, pparams.hDeviceWindow, D3DCREATE_FPU_PRESERVE | ((caps. DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING), &pparams, &data->device); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("CreateDevice()", result); return NULL; } data->beginScene = SDL_TRUE; data->scaleMode = D3DTEXF_FORCE_DWORD; /* Get presentation parameters to fill info */ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("GetSwapChain()", result); return NULL; } result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); if (FAILED(result)) { IDirect3DSwapChain9_Release(chain); D3D_DestroyRenderer(renderer); D3D_SetError("GetPresentParameters()", result); return NULL; } IDirect3DSwapChain9_Release(chain); if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } data->pparams = pparams; IDirect3DDevice9_GetDeviceCaps(data->device, &caps); renderer->info.max_texture_width = caps.MaxTextureWidth; renderer->info.max_texture_height = caps.MaxTextureHeight; if (caps.NumSimultaneousRTs >= 2) { renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; } /* Set up parameters for rendering */ IDirect3DDevice9_SetVertexShader(data->device, NULL); IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); /* Enable color modulation by diffuse color */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); /* Enable alpha modulation by diffuse alpha */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); /* Disable second texture stage, since we're done */ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); /* Store the default render target */ IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget ); data->currentRenderTarget = NULL; /* Set an identity world and view matrix */ matrix.m[0][0] = 1.0f; matrix.m[0][1] = 0.0f; matrix.m[0][2] = 0.0f; matrix.m[0][3] = 0.0f; matrix.m[1][0] = 0.0f; matrix.m[1][1] = 1.0f; matrix.m[1][2] = 0.0f; matrix.m[1][3] = 0.0f; matrix.m[2][0] = 0.0f; matrix.m[2][1] = 0.0f; matrix.m[2][2] = 1.0f; matrix.m[2][3] = 0.0f; matrix.m[3][0] = 0.0f; matrix.m[3][1] = 0.0f; matrix.m[3][2] = 0.0f; matrix.m[3][3] = 1.0f; IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix); IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix); return renderer; }
/* Helper function */ static void set_states(ID3DXSpriteImpl *object) { D3DXMATRIX mat; D3DVIEWPORT9 vp; /* Miscellaneous stuff */ IDirect3DDevice9_SetVertexShader(object->device, NULL); IDirect3DDevice9_SetPixelShader(object->device, NULL); IDirect3DDevice9_SetNPatchMode(object->device, 0.0f); /* Render states */ IDirect3DDevice9_SetRenderState(object->device, D3DRS_ALPHABLENDENABLE, TRUE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); IDirect3DDevice9_SetRenderState(object->device, D3DRS_ALPHAREF, 0x00); IDirect3DDevice9_SetRenderState(object->device, D3DRS_ALPHATESTENABLE, object->alphacmp_caps); IDirect3DDevice9_SetRenderState(object->device, D3DRS_BLENDOP, D3DBLENDOP_ADD); IDirect3DDevice9_SetRenderState(object->device, D3DRS_CLIPPING, TRUE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_CLIPPLANEENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); IDirect3DDevice9_SetRenderState(object->device, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); IDirect3DDevice9_SetRenderState(object->device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); IDirect3DDevice9_SetRenderState(object->device, D3DRS_ENABLEADAPTIVETESSELLATION, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_FILLMODE, D3DFILL_SOLID); IDirect3DDevice9_SetRenderState(object->device, D3DRS_FOGENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_LIGHTING, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_RANGEFOGENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_SEPARATEALPHABLENDENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_SHADEMODE, D3DSHADE_GOURAUD); IDirect3DDevice9_SetRenderState(object->device, D3DRS_SPECULARENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); IDirect3DDevice9_SetRenderState(object->device, D3DRS_SRGBWRITEENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_STENCILENABLE, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_VERTEXBLEND, FALSE); IDirect3DDevice9_SetRenderState(object->device, D3DRS_WRAP0, 0); /* Texture stage states */ IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_TEXCOORDINDEX, 0); IDirect3DDevice9_SetTextureStageState(object->device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); IDirect3DDevice9_SetTextureStageState(object->device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(object->device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); /* Sampler states */ IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); if(object->texfilter_caps & D3DPTFILTERCAPS_MAGFANISOTROPIC) IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); else IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MAXMIPLEVEL, 0); IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MAXANISOTROPY, object->maxanisotropy); if(object->texfilter_caps & D3DPTFILTERCAPS_MINFANISOTROPIC) IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); else IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); if(object->texfilter_caps & D3DPTFILTERCAPS_MIPFLINEAR) IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); else IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_MIPMAPLODBIAS, 0); IDirect3DDevice9_SetSamplerState(object->device, 0, D3DSAMP_SRGBTEXTURE, 0); /* Matrices */ D3DXMatrixIdentity(&mat); IDirect3DDevice9_SetTransform(object->device, D3DTS_WORLD, &mat); IDirect3DDevice9_SetTransform(object->device, D3DTS_VIEW, &object->view); IDirect3DDevice9_GetViewport(object->device, &vp); D3DXMatrixOrthoOffCenterLH(&mat, vp.X+0.5f, (float)vp.Width+vp.X+0.5f, (float)vp.Height+vp.Y+0.5f, vp.Y+0.5f, vp.MinZ, vp.MaxZ); IDirect3DDevice9_SetTransform(object->device, D3DTS_PROJECTION, &mat); }
SDL_Renderer * D3D_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata; SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_Renderer *renderer; D3D_RenderData *data; HRESULT result; D3DPRESENT_PARAMETERS pparams; IDirect3DSwapChain9 *chain; D3DCAPS9 caps; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { D3D_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } data->d3d = videodata->d3d; renderer->DisplayModeChanged = D3D_DisplayModeChanged; renderer->CreateTexture = D3D_CreateTexture; renderer->QueryTexturePixels = D3D_QueryTexturePixels; renderer->SetTexturePalette = D3D_SetTexturePalette; renderer->GetTexturePalette = D3D_GetTexturePalette; renderer->SetTextureColorMod = D3D_SetTextureColorMod; renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod; renderer->SetTextureBlendMode = D3D_SetTextureBlendMode; renderer->SetTextureScaleMode = D3D_SetTextureScaleMode; renderer->UpdateTexture = D3D_UpdateTexture; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; renderer->DirtyTexture = D3D_DirtyTexture; renderer->RenderPoint = D3D_RenderPoint; renderer->RenderLine = D3D_RenderLine; renderer->RenderFill = D3D_RenderFill; renderer->RenderCopy = D3D_RenderCopy; renderer->RenderPresent = D3D_RenderPresent; renderer->DestroyTexture = D3D_DestroyTexture; renderer->DestroyRenderer = D3D_DestroyRenderer; renderer->info = D3D_RenderDriver.info; renderer->window = window->id; renderer->driverdata = data; renderer->info.flags = SDL_RENDERER_ACCELERATED; SDL_zero(pparams); pparams.BackBufferWidth = window->w; pparams.BackBufferHeight = window->h; if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.BackBufferFormat = PixelFormatToD3DFMT(display->fullscreen_mode.format); } else { pparams.BackBufferFormat = D3DFMT_UNKNOWN; } if (flags & SDL_RENDERER_PRESENTFLIP2) { pparams.BackBufferCount = 2; pparams.SwapEffect = D3DSWAPEFFECT_FLIP; } else if (flags & SDL_RENDERER_PRESENTFLIP3) { pparams.BackBufferCount = 3; pparams.SwapEffect = D3DSWAPEFFECT_FLIP; } else if (flags & SDL_RENDERER_PRESENTCOPY) { pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_COPY; } else { pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; } if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = display->fullscreen_mode.refresh_rate; } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; } if (flags & SDL_RENDERER_PRESENTVSYNC) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } IDirect3D9_GetDeviceCaps(videodata->d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT, /* FIXME */ D3DDEVTYPE_HAL, windowdata->hwnd, (caps. DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pparams, &data->device); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("CreateDevice()", result); return NULL; } data->beginScene = SDL_TRUE; /* Get presentation parameters to fill info */ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("GetSwapChain()", result); return NULL; } result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); if (FAILED(result)) { IDirect3DSwapChain9_Release(chain); D3D_DestroyRenderer(renderer); D3D_SetError("GetPresentParameters()", result); return NULL; } IDirect3DSwapChain9_Release(chain); switch (pparams.SwapEffect) { case D3DSWAPEFFECT_COPY: renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; break; case D3DSWAPEFFECT_FLIP: switch (pparams.BackBufferCount) { case 2: renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; break; case 3: renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; break; } break; case D3DSWAPEFFECT_DISCARD: renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD; break; } if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } data->pparams = pparams; IDirect3DDevice9_GetDeviceCaps(data->device, &caps); renderer->info.max_texture_width = caps.MaxTextureWidth; renderer->info.max_texture_height = caps.MaxTextureHeight; /* Set up parameters for rendering */ IDirect3DDevice9_SetVertexShader(data->device, NULL); IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); /* Enable color modulation by diffuse color */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); /* Enable alpha modulation by diffuse alpha */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); /* Disable second texture stage, since we're done */ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); return renderer; }
int main( void ) { LPDIRECT3DVERTEXBUFFER9 v_buffer; sgui_window_description desc; IDirect3DTexture9* texture; sgui_d3d9_context* ctx; sgui_canvas* texcanvas; IDirect3DDevice9* dev; sgui_widget* check2; sgui_widget* check; sgui_widget* butt; sgui_window* wnd; float a=0.0f; VOID* pVoid; float m[16]; sgui_init( ); /*************************** create a window **************************/ desc.parent = NULL; desc.share = NULL; desc.width = 640; desc.height = 480; desc.flags = SGUI_FIXED_SIZE|SGUI_DOUBLEBUFFERED; desc.backend = SGUI_DIRECT3D_9; desc.bits_per_pixel = 32; desc.depth_bits = 16; desc.stencil_bits = 0; desc.samples = 0; wnd = sgui_window_create_desc( &desc ); sgui_window_set_title( wnd, "Direct3D 9 Texture Canvas" ); sgui_window_move_center( wnd ); sgui_window_set_visible( wnd, SGUI_VISIBLE ); sgui_window_set_vsync( wnd, 1 ); /************************ createtexture canvas ************************/ texcanvas = sgui_tex_canvas_create( wnd, sgui_window_get_context( wnd ), 128, 128 ); butt = sgui_button_create( 10, 10, 60, 25, "Button", 0 ); check = sgui_checkbox_create( 10, 40, "Direct3D" ); check2 = sgui_checkbox_create( 10, 65, "Texture" ); sgui_button_set_state( check, 1 ); sgui_button_set_state( check2, 1 ); sgui_widget_add_child( &texcanvas->root, butt ); sgui_widget_add_child( &texcanvas->root, check ); sgui_widget_add_child( &texcanvas->root, check2 ); /************** connect keyboard input to texture canvas **************/ sgui_event_connect( wnd, SGUI_KEY_PRESSED_EVENT, sgui_canvas_send_window_event, texcanvas, SGUI_FROM_EVENT, SGUI_EVENT ); sgui_event_connect( wnd, SGUI_KEY_RELEASED_EVENT, sgui_canvas_send_window_event, texcanvas, SGUI_FROM_EVENT, SGUI_EVENT ); sgui_event_connect( wnd, SGUI_CHAR_EVENT, sgui_canvas_send_window_event, texcanvas, SGUI_FROM_EVENT, SGUI_EVENT ); /*************************** Direct3D setup ***************************/ /* get the device context, set new present parameters */ ctx = (sgui_d3d9_context*)sgui_window_get_context( wnd ); dev = ctx->device; IDirect3DDevice9_Reset( dev, &ctx->present ); /* create a vertex buffer */ IDirect3DDevice9_CreateVertexBuffer( dev, sizeof(vertices), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL ); /* load vertex data */ IDirect3DVertexBuffer9_Lock( v_buffer, 0, 0, (void**)&pVoid, 0 ); memcpy( pVoid, vertices, sizeof(vertices) ); IDirect3DVertexBuffer9_Unlock( v_buffer ); /* setup renderer state */ IDirect3DDevice9_SetRenderState( dev, D3DRS_CULLMODE, D3DCULL_NONE ); IDirect3DDevice9_SetRenderState( dev, D3DRS_LIGHTING, FALSE ); IDirect3DDevice9_SetRenderState( dev, D3DRS_ZENABLE, TRUE ); /* set up perspective projection matrix */ perspective( m, 45.0f, (float)desc.width/(float)desc.height, 0.1f, 100.0f ); IDirect3DDevice9_SetTransform( dev, D3DTS_PROJECTION, (D3DMATRIX*)m ); /* set up texturing, bind canvas texture to stage 0 */ texture = sgui_tex_canvas_get_texture( texcanvas ); IDirect3DDevice9_SetTexture( dev, 0, (IDirect3DBaseTexture9*)texture ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); IDirect3DDevice9_SetSamplerState(dev,0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); IDirect3DDevice9_SetSamplerState(dev,0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); /****************************** main loop *****************************/ while( sgui_main_loop_step( ) ) { /* redraw widgets in dirty areas */ sgui_canvas_redraw_widgets( texcanvas, 1 ); /* draw scene */ IDirect3DDevice9_Clear( dev, 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0 ); IDirect3DDevice9_BeginScene( dev ); transform( m, a ); IDirect3DDevice9_SetTransform( dev, D3DTS_VIEW, (D3DMATRIX*)m ); a += 0.01f; IDirect3DDevice9_SetFVF( dev, CUSTOMFVF ); IDirect3DDevice9_SetStreamSource( dev, 0, v_buffer, 0, sizeof(CUSTOMVERTEX) ); IDirect3DDevice9_DrawPrimitive( dev, D3DPT_TRIANGLELIST, 0, 8 ); IDirect3DDevice9_EndScene( dev ); /* swap front and back buffer */ sgui_window_swap_buffers( wnd ); } /****************************** clean up ******************************/ sgui_canvas_destroy( texcanvas ); sgui_widget_destroy( check2 ); sgui_widget_destroy( check ); sgui_widget_destroy( butt ); IDirect3DVertexBuffer9_Release( v_buffer ); sgui_window_destroy( wnd ); sgui_deinit( ); return 0; }