-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Am 2015-07-08 um 19:58 schrieb Aaryaman Vasishta:
- hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
- IDirect3DRMDevice3_Release(device3);
- if (FAILED(hr))
return hr;
- return D3DRM_OK;
Minor style point: The if check here is redundant, you can just use "return hr;" here.
- hr = DirectDrawCreate(NULL, &ddraw, NULL);
- if (FAILED(hr))
return hr;
- hr = IDirectDrawClipper_GetHWnd(clipper, &window);
- if (FAILED(hr))
return hr;
- hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
- if (FAILED(hr))
return hr;
...
This leaks ddraw in a number of cases. same for device and surface later on.
- hr = Direct3DRMDevice_create(&IID_IDirect3DRMDevice3, (IUnknown **)device);
- if (FAILED(hr))
return hr;
I recommend to add a forward declaration of struct d3drm_device to d3drm_private.h and make Direct3DRMDevice_create return a struct d3drm_device ** instead of an IUnknown. That way you can keep the actual structure in device.c and avoid the ugly void * + version hacks.
Have a look at how struct wined3d_device works in include/wine/wined3d.h and dlls/wined3d/wined3d_private.h for example.
Instead of calling IDirect3DRMDevice_Release() if the creation fails add a d3drm_device_destroy() helper function. If you need the different release behavior some day you can have the InterlockedDecrement() == 0 in each Release method and call d3drm_device_destroy.
- hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
I suggest to rename "surface" to "render_target".
+void set_primary_surface(void **device, UINT version, IDirectDrawClipper *clipper, IDirectDrawSurface *primary_surface) +{
- struct d3drm_device *object;
...
- object->primary_surface = primary_surface;
- object->clipper = clipper;
- IDirectDrawClipper_AddRef(clipper);
+}
Is there really a need to store (and AddRef) the clipper? The primary surface already keeps a reference to it, so you should be OK. It won't give you the increment by 2 that native has though, but I don't think that's important.
hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
if (FAILED(hr))
return hr;
hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
if (FAILED(hr))
{
IDirectDrawSurface_Release(ds);
return hr;
}
Similarly: Is there a need to store the depth stencil? You could just release your reference after attaching it to the render target, it will stay alive anyway. (If it's just for the DeleteAttachedSurface later: Ignore it)
Releasing ds right after AddAttachedSurface would simplify your Release() method a bit. Also keep in mind that you can always use GetAttachedSurface to get the depth stencil. That may be even more correct because the application can in theory change the depth stencil after creating the device.
(Possible problem: The device attaches another depth stencil, yours dies. Is this a problem? I'd say don't bother as long as no app does it. Offscreen rendering and depth buffer switching didn't exactly work well prior to d3d8, even though the API in theory supported it)
You have to keep ddraw alive because nothing (neither your surfaces nor your device) hold a reference to it. Same for the primary. I think it's also good to store a reference to the render target, I believe you need it to show the rendering results on the screen (The immediate mode device holds a ref too, but it's awkward to always query it from the device).
- if (device->ref == 1 && device->z_created_internally)
IDirectDrawSurface_DeleteAttachedSurface(device->render_target, 0, device->depth_surface);
As mentioned on IRC this is not thread safe A lot can happen between your ref == 1 comparison and the actual InterlockedDecrement.
Wrt patch 6 (d3drm1_CreateDeviceFromClipper): It's a bit unfortunate that this is mostly a copypasted version of version 3, and the difference that actually matters is in init_device anyway. Maybe there is a nicer solution, e.g. a helper function for v1 and v3 with a version parameter.
- hr = Direct3DRMDevice_create(&IID_IDirect3DRMDevice, (IUnknown **)device);
- if (FAILED(hr))
return hr;
- desc.dwSize = sizeof(desc);
- hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer, &desc);
- if (FAILED(hr))
- {
IDirect3DRMDevice_Release(*device);
return hr;
- }
You can reorder these calls, then you don't have to release *device.