d2d1: Implement d2d_d3d_render_target_CreateBitmap().
[wine/multimedia.git] / dlls / d2d1 / render_target.c
blob2c501efe5ad7c0eb6bda9a5064467722c7a4b041
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include "d2d1_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
26 #define INITIAL_CLIP_STACK_SIZE 4
28 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
30 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
31 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
34 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
36 if (point->x < dst->left)
37 dst->left = point->x;
38 if (point->y < dst->top)
39 dst->top = point->y;
40 if (point->x > dst->right)
41 dst->right = point->x;
42 if (point->y > dst->bottom)
43 dst->bottom = point->y;
46 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
48 if (src->left > dst->left)
49 dst->left = src->left;
50 if (src->top > dst->top)
51 dst->top = src->top;
52 if (src->right < dst->right)
53 dst->right = src->right;
54 if (src->bottom < dst->bottom)
55 dst->bottom = src->bottom;
58 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
60 dst->left = left;
61 dst->top = top;
62 dst->right = right;
63 dst->bottom = bottom;
66 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
68 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
69 return FALSE;
71 stack->size = INITIAL_CLIP_STACK_SIZE;
72 stack->count = 0;
74 return TRUE;
77 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
79 HeapFree(GetProcessHeap(), 0, stack->stack);
82 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
84 D2D1_RECT_F r;
86 if (stack->count == stack->size)
88 D2D1_RECT_F *new_stack;
89 unsigned int new_size;
91 if (stack->size > UINT_MAX / 2)
92 return FALSE;
94 new_size = stack->size * 2;
95 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
96 return FALSE;
98 stack->stack = new_stack;
99 stack->size = new_size;
102 r = *rect;
103 if (stack->count)
104 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
105 stack->stack[stack->count++] = r;
107 return TRUE;
110 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
112 if (!stack->count)
113 return;
114 --stack->count;
117 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
119 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
122 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
124 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
126 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
127 || IsEqualGUID(iid, &IID_ID2D1Resource)
128 || IsEqualGUID(iid, &IID_IUnknown))
130 ID2D1RenderTarget_AddRef(iface);
131 *out = iface;
132 return S_OK;
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
137 *out = NULL;
138 return E_NOINTERFACE;
141 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
143 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
144 ULONG refcount = InterlockedIncrement(&render_target->refcount);
146 TRACE("%p increasing refcount to %u.\n", iface, refcount);
148 return refcount;
151 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
153 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
154 ULONG refcount = InterlockedDecrement(&render_target->refcount);
156 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
158 if (!refcount)
160 d2d_clip_stack_cleanup(&render_target->clip_stack);
161 ID3D10RenderTargetView_Release(render_target->view);
162 ID3D10RasterizerState_Release(render_target->clear_rs);
163 ID3D10PixelShader_Release(render_target->clear_ps);
164 ID3D10VertexShader_Release(render_target->clear_vs);
165 ID3D10Buffer_Release(render_target->clear_vb);
166 ID3D10InputLayout_Release(render_target->clear_il);
167 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
168 ID3D10Device_Release(render_target->device);
169 HeapFree(GetProcessHeap(), 0, render_target);
172 return refcount;
175 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
177 FIXME("iface %p, factory %p stub!\n", iface, factory);
179 *factory = NULL;
182 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
183 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
185 struct d2d_bitmap *object;
187 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
188 iface, size.width, size.height, src_data, pitch, desc, bitmap);
190 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
191 return E_OUTOFMEMORY;
193 d2d_bitmap_init(object, size, src_data, pitch, desc);
195 TRACE("Created bitmap %p.\n", object);
196 *bitmap = &object->ID2D1Bitmap_iface;
198 return S_OK;
201 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
202 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
204 FIXME("iface %p, bitmap_source %p, desc %p, bitmap %p stub!\n",
205 iface, bitmap_source, desc, bitmap);
207 return E_NOTIMPL;
210 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
211 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
213 FIXME("iface %p, iid %s, data %p, desc %p, bitmap %p stub!\n",
214 iface, debugstr_guid(iid), data, desc, bitmap);
216 return E_NOTIMPL;
219 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
220 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
221 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
223 FIXME("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p stub!\n",
224 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
226 return E_NOTIMPL;
229 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
230 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
232 struct d2d_brush *object;
234 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
236 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
237 return E_OUTOFMEMORY;
239 d2d_solid_color_brush_init(object, iface, color, desc);
241 TRACE("Created brush %p.\n", object);
242 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
244 return S_OK;
247 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
248 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
249 ID2D1GradientStopCollection **gradient)
251 struct d2d_gradient *object;
253 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
254 iface, stops, stop_count, gamma, extend_mode, gradient);
256 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
257 return E_OUTOFMEMORY;
259 d2d_gradient_init(object, iface, stops, stop_count, gamma, extend_mode);
261 TRACE("Created gradient %p.\n", object);
262 *gradient = &object->ID2D1GradientStopCollection_iface;
264 return S_OK;
267 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
268 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
269 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
271 struct d2d_brush *object;
273 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
274 iface, gradient_brush_desc, brush_desc, gradient, brush);
276 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
277 return E_OUTOFMEMORY;
279 d2d_linear_gradient_brush_init(object, iface, gradient_brush_desc, brush_desc, gradient);
281 TRACE("Created brush %p.\n", object);
282 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
284 return S_OK;
287 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
288 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
289 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
291 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
292 iface, gradient_brush_desc, brush_desc, gradient, brush);
294 return E_NOTIMPL;
297 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
298 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
299 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
301 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
302 iface, size, pixel_size, format, options, render_target);
304 return E_NOTIMPL;
307 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
308 const D2D1_SIZE_F *size, ID2D1Layer **layer)
310 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
312 return E_NOTIMPL;
315 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
317 struct d2d_mesh *object;
319 TRACE("iface %p, mesh %p.\n", iface, mesh);
321 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
322 return E_OUTOFMEMORY;
324 d2d_mesh_init(object);
326 TRACE("Created mesh %p.\n", object);
327 *mesh = &object->ID2D1Mesh_iface;
329 return S_OK;
332 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
333 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
335 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
336 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
339 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
340 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
342 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
343 iface, rect, brush, stroke_width, stroke_style);
346 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
347 const D2D1_RECT_F *rect, ID2D1Brush *brush)
349 FIXME("iface %p, rect %p, brush %p stub!\n", iface, rect, brush);
352 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
353 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
355 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
356 iface, rect, brush, stroke_width, stroke_style);
359 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
360 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
362 FIXME("iface %p, rect %p, brush %p stub!\n", iface, rect, brush);
365 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
366 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
368 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
369 iface, ellipse, brush, stroke_width, stroke_style);
372 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
373 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
375 FIXME("iface %p, ellipse %p, brush %p stub!\n", iface, ellipse, brush);
378 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
379 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
381 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
382 iface, geometry, brush, stroke_width, stroke_style);
385 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
386 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
388 FIXME("iface %p, geometry %p, brush %p, opacity_brush %p stub!\n", iface, geometry, brush, opacity_brush);
391 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
392 ID2D1Mesh *mesh, ID2D1Brush *brush)
394 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
397 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
398 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
399 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
401 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
402 iface, mask, brush, content, dst_rect, src_rect);
405 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
406 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
407 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
409 FIXME("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p stub!\n",
410 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
413 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
414 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
415 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
417 FIXME("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
418 "brush %p, options %#x, measuring_mode %#x stub!\n",
419 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
420 brush, options, measuring_mode);
423 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
424 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
426 FIXME("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x stub!\n",
427 iface, origin.x, origin.y, layout, brush, options);
430 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
431 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
432 DWRITE_MEASURING_MODE measuring_mode)
434 FIXME("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x stub!\n",
435 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
438 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
439 const D2D1_MATRIX_3X2_F *transform)
441 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
443 TRACE("iface %p, transform %p.\n", iface, transform);
445 render_target->transform = *transform;
448 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
449 D2D1_MATRIX_3X2_F *transform)
451 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
453 TRACE("iface %p, transform %p.\n", iface, transform);
455 *transform = render_target->transform;
458 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
459 D2D1_ANTIALIAS_MODE antialias_mode)
461 FIXME("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
464 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
466 FIXME("iface %p stub!\n", iface);
468 return D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
471 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
472 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
474 FIXME("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
477 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
479 FIXME("iface %p stub!\n", iface);
481 return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
484 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
485 IDWriteRenderingParams *text_rendering_params)
487 FIXME("iface %p, text_rendering_params %p stub!\n", iface, text_rendering_params);
490 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
491 IDWriteRenderingParams **text_rendering_params)
493 FIXME("iface %p, text_rendering_params %p stub!\n", iface, text_rendering_params);
495 *text_rendering_params = NULL;
498 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
500 FIXME("iface %p, tag1 %s, tag2 %s stub!\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
503 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
505 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
507 *tag1 = 0;
508 *tag2 = 0;
511 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
512 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
514 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
517 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
519 FIXME("iface %p stub!\n", iface);
522 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
524 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
526 return E_NOTIMPL;
529 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
530 ID2D1DrawingStateBlock *state_block)
532 FIXME("iface %p, state_block %p stub!\n", iface, state_block);
535 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
536 ID2D1DrawingStateBlock *state_block)
538 FIXME("iface %p, state_block %p stub!\n", iface, state_block);
541 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
542 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
544 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
545 D2D1_RECT_F transformed_rect;
546 float x_scale, y_scale;
547 D2D1_POINT_2F point;
549 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
551 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
552 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
554 x_scale = render_target->dpi_x / 96.0f;
555 y_scale = render_target->dpi_y / 96.0f;
556 d2d_point_transform(&point, &render_target->transform, clip_rect->left * x_scale, clip_rect->top * y_scale);
557 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
558 d2d_point_transform(&point, &render_target->transform, clip_rect->left * x_scale, clip_rect->bottom * y_scale);
559 d2d_rect_expand(&transformed_rect, &point);
560 d2d_point_transform(&point, &render_target->transform, clip_rect->right * x_scale, clip_rect->top * y_scale);
561 d2d_rect_expand(&transformed_rect, &point);
562 d2d_point_transform(&point, &render_target->transform, clip_rect->right * x_scale, clip_rect->bottom * y_scale);
563 d2d_rect_expand(&transformed_rect, &point);
565 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
566 WARN("Failed to push clip rect.\n");
569 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
571 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
573 TRACE("iface %p.\n", iface);
575 d2d_clip_stack_pop(&render_target->clip_stack);
578 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
580 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
581 D3D10_SUBRESOURCE_DATA buffer_data;
582 D3D10_BUFFER_DESC buffer_desc;
583 unsigned int offset;
584 D3D10_VIEWPORT vp;
585 ID3D10Buffer *cb;
586 HRESULT hr;
588 TRACE("iface %p, color %p.\n", iface, color);
590 buffer_desc.ByteWidth = sizeof(*color);
591 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
592 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
593 buffer_desc.CPUAccessFlags = 0;
594 buffer_desc.MiscFlags = 0;
596 buffer_data.pSysMem = color;
597 buffer_data.SysMemPitch = 0;
598 buffer_data.SysMemSlicePitch = 0;
600 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &cb)))
602 WARN("Failed to create constant buffer, hr %#x.\n", hr);
603 return;
606 vp.TopLeftX = 0;
607 vp.TopLeftY = 0;
608 vp.Width = render_target->pixel_size.width;
609 vp.Height = render_target->pixel_size.height;
610 vp.MinDepth = 0.0f;
611 vp.MaxDepth = 1.0f;
613 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
615 WARN("Failed to capture stateblock, hr %#x.\n", hr);
616 ID3D10Buffer_Release(cb);
617 return;
620 ID3D10Device_ClearState(render_target->device);
622 ID3D10Device_IASetInputLayout(render_target->device, render_target->clear_il);
623 ID3D10Device_IASetPrimitiveTopology(render_target->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
624 offset = 0;
625 ID3D10Device_IASetVertexBuffers(render_target->device, 0, 1,
626 &render_target->clear_vb, &render_target->clear_vb_stride, &offset);
627 ID3D10Device_VSSetShader(render_target->device, render_target->clear_vs);
628 ID3D10Device_PSSetConstantBuffers(render_target->device, 0, 1, &cb);
629 ID3D10Device_PSSetShader(render_target->device, render_target->clear_ps);
630 ID3D10Device_RSSetViewports(render_target->device, 1, &vp);
631 if (render_target->clip_stack.count)
633 const D2D1_RECT_F *clip_rect;
634 D3D10_RECT scissor_rect;
636 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
637 scissor_rect.left = clip_rect->left + 0.5f;
638 scissor_rect.top = clip_rect->top + 0.5f;
639 scissor_rect.right = clip_rect->right + 0.5f;
640 scissor_rect.bottom = clip_rect->bottom + 0.5f;
641 ID3D10Device_RSSetScissorRects(render_target->device, 1, &scissor_rect);
642 ID3D10Device_RSSetState(render_target->device, render_target->clear_rs);
644 ID3D10Device_OMSetRenderTargets(render_target->device, 1, &render_target->view, NULL);
646 ID3D10Device_Draw(render_target->device, 4, 0);
648 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
649 WARN("Failed to apply stateblock, hr %#x.\n", hr);
651 ID3D10Buffer_Release(cb);
654 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
656 TRACE("iface %p.\n", iface);
659 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
660 D2D1_TAG *tag1, D2D1_TAG *tag2)
662 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
664 if (tag1)
665 *tag1 = 0;
666 if (tag2)
667 *tag2 = 0;
669 return S_OK;
672 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
673 D2D1_PIXEL_FORMAT *format)
675 FIXME("iface %p, format %p stub!\n", iface, format);
677 format->format = DXGI_FORMAT_UNKNOWN;
678 format->alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
679 return format;
682 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
684 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
686 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
688 if (dpi_x == 0.0f && dpi_y == 0.0f)
690 dpi_x = 96.0f;
691 dpi_y = 96.0f;
694 render_target->dpi_x = dpi_x;
695 render_target->dpi_y = dpi_y;
698 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
700 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
702 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
704 *dpi_x = render_target->dpi_x;
705 *dpi_y = render_target->dpi_y;
708 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
710 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
712 TRACE("iface %p, size %p.\n", iface, size);
714 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
715 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
716 return size;
719 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
720 D2D1_SIZE_U *pixel_size)
722 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
724 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
726 *pixel_size = render_target->pixel_size;
727 return pixel_size;
730 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
732 FIXME("iface %p stub!\n", iface);
734 return 0;
737 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
738 const D2D1_RENDER_TARGET_PROPERTIES *desc)
740 FIXME("iface %p, desc %p stub!\n", iface, desc);
742 return FALSE;
745 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
747 d2d_d3d_render_target_QueryInterface,
748 d2d_d3d_render_target_AddRef,
749 d2d_d3d_render_target_Release,
750 d2d_d3d_render_target_GetFactory,
751 d2d_d3d_render_target_CreateBitmap,
752 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
753 d2d_d3d_render_target_CreateSharedBitmap,
754 d2d_d3d_render_target_CreateBitmapBrush,
755 d2d_d3d_render_target_CreateSolidColorBrush,
756 d2d_d3d_render_target_CreateGradientStopCollection,
757 d2d_d3d_render_target_CreateLinearGradientBrush,
758 d2d_d3d_render_target_CreateRadialGradientBrush,
759 d2d_d3d_render_target_CreateCompatibleRenderTarget,
760 d2d_d3d_render_target_CreateLayer,
761 d2d_d3d_render_target_CreateMesh,
762 d2d_d3d_render_target_DrawLine,
763 d2d_d3d_render_target_DrawRectangle,
764 d2d_d3d_render_target_FillRectangle,
765 d2d_d3d_render_target_DrawRoundedRectangle,
766 d2d_d3d_render_target_FillRoundedRectangle,
767 d2d_d3d_render_target_DrawEllipse,
768 d2d_d3d_render_target_FillEllipse,
769 d2d_d3d_render_target_DrawGeometry,
770 d2d_d3d_render_target_FillGeometry,
771 d2d_d3d_render_target_FillMesh,
772 d2d_d3d_render_target_FillOpacityMask,
773 d2d_d3d_render_target_DrawBitmap,
774 d2d_d3d_render_target_DrawText,
775 d2d_d3d_render_target_DrawTextLayout,
776 d2d_d3d_render_target_DrawGlyphRun,
777 d2d_d3d_render_target_SetTransform,
778 d2d_d3d_render_target_GetTransform,
779 d2d_d3d_render_target_SetAntialiasMode,
780 d2d_d3d_render_target_GetAntialiasMode,
781 d2d_d3d_render_target_SetTextAntialiasMode,
782 d2d_d3d_render_target_GetTextAntialiasMode,
783 d2d_d3d_render_target_SetTextRenderingParams,
784 d2d_d3d_render_target_GetTextRenderingParams,
785 d2d_d3d_render_target_SetTags,
786 d2d_d3d_render_target_GetTags,
787 d2d_d3d_render_target_PushLayer,
788 d2d_d3d_render_target_PopLayer,
789 d2d_d3d_render_target_Flush,
790 d2d_d3d_render_target_SaveDrawingState,
791 d2d_d3d_render_target_RestoreDrawingState,
792 d2d_d3d_render_target_PushAxisAlignedClip,
793 d2d_d3d_render_target_PopAxisAlignedClip,
794 d2d_d3d_render_target_Clear,
795 d2d_d3d_render_target_BeginDraw,
796 d2d_d3d_render_target_EndDraw,
797 d2d_d3d_render_target_GetPixelFormat,
798 d2d_d3d_render_target_SetDpi,
799 d2d_d3d_render_target_GetDpi,
800 d2d_d3d_render_target_GetSize,
801 d2d_d3d_render_target_GetPixelSize,
802 d2d_d3d_render_target_GetMaximumBitmapSize,
803 d2d_d3d_render_target_IsSupported,
806 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
807 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
809 D3D10_SUBRESOURCE_DATA buffer_data;
810 D3D10_STATE_BLOCK_MASK state_mask;
811 DXGI_SURFACE_DESC surface_desc;
812 D3D10_RASTERIZER_DESC rs_desc;
813 D3D10_BUFFER_DESC buffer_desc;
814 ID3D10Resource *resource;
815 HRESULT hr;
817 static const D3D10_INPUT_ELEMENT_DESC clear_il_desc[] =
819 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
821 static const DWORD clear_vs_code[] =
823 /* float4 main(float4 position : POSITION) : SV_POSITION
825 * return position;
826 * } */
827 0x43425844, 0x1fa8c27f, 0x52d2f21d, 0xc196fdb7, 0x376f283a, 0x00000001, 0x000001b4, 0x00000005,
828 0x00000034, 0x0000008c, 0x000000c0, 0x000000f4, 0x00000138, 0x46454452, 0x00000050, 0x00000000,
829 0x00000000, 0x00000000, 0x0000001c, 0xfffe0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
830 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e30332e,
831 0x30303239, 0x3336312e, 0xab003438, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
832 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
833 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
834 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040,
835 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
836 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074,
837 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
838 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
839 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
840 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
842 static const DWORD clear_ps_code[] =
844 /* float4 color;
846 * float4 main(float4 position : SV_POSITION) : SV_Target
848 * return color;
849 * } */
850 0x43425844, 0xecd3cc9d, 0x0025bc77, 0x7a333165, 0x5b04c7e4, 0x00000001, 0x0000022c, 0x00000005,
851 0x00000034, 0x00000100, 0x00000134, 0x00000168, 0x000001b0, 0x46454452, 0x000000c4, 0x00000001,
852 0x00000048, 0x00000001, 0x0000001c, 0xffff0400, 0x00000100, 0x00000090, 0x0000003c, 0x00000000,
853 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x6f6c4724, 0x736c6162,
854 0xababab00, 0x0000003c, 0x00000001, 0x00000060, 0x00000010, 0x00000000, 0x00000000, 0x00000078,
855 0x00000000, 0x00000010, 0x00000002, 0x00000080, 0x00000000, 0x6f6c6f63, 0xabab0072, 0x00030001,
856 0x00040001, 0x00000000, 0x00000000, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53,
857 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e30332e, 0x30303239, 0x3336312e, 0xab003438,
858 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
859 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001,
860 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653,
861 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040, 0x00000010, 0x04000059, 0x00208e46,
862 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x06000036, 0x001020f2, 0x00000000,
863 0x00208e46, 0x00000000, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
864 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
865 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
866 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
867 0x00000000, 0x00000000, 0x00000000,
869 static const struct
871 float x, y;
873 clear_quad[] =
875 {-1.0f, -1.0f},
876 {-1.0f, 1.0f},
877 { 1.0f, -1.0f},
878 { 1.0f, 1.0f},
880 static const D2D1_MATRIX_3X2_F identity =
882 1.0f, 0.0f,
883 0.0f, 1.0f,
884 0.0f, 0.0f,
887 FIXME("Ignoring render target properties.\n");
889 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
890 render_target->refcount = 1;
892 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
894 WARN("Failed to get device interface, hr %#x.\n", hr);
895 return hr;
898 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
900 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
901 goto err;
904 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
905 ID3D10Resource_Release(resource);
906 if (FAILED(hr))
908 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
909 goto err;
912 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
914 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
915 goto err;
918 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
920 WARN("Failed to create stateblock, hr %#x.\n", hr);
921 goto err;
924 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, clear_il_desc,
925 sizeof(clear_il_desc) / sizeof(*clear_il_desc), clear_vs_code, sizeof(clear_vs_code),
926 &render_target->clear_il)))
928 WARN("Failed to create clear input layout, hr %#x.\n", hr);
929 goto err;
932 buffer_desc.ByteWidth = sizeof(clear_quad);
933 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
934 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
935 buffer_desc.CPUAccessFlags = 0;
936 buffer_desc.MiscFlags = 0;
938 buffer_data.pSysMem = clear_quad;
939 buffer_data.SysMemPitch = 0;
940 buffer_data.SysMemSlicePitch = 0;
942 render_target->clear_vb_stride = sizeof(*clear_quad);
943 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
944 &buffer_desc, &buffer_data, &render_target->clear_vb)))
946 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
947 goto err;
950 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device,
951 clear_vs_code, sizeof(clear_vs_code), &render_target->clear_vs)))
953 WARN("Failed to create clear vertex shader, hr %#x.\n", hr);
954 goto err;
957 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
958 clear_ps_code, sizeof(clear_ps_code), &render_target->clear_ps)))
960 WARN("Failed to create clear pixel shader, hr %#x.\n", hr);
961 goto err;
964 rs_desc.FillMode = D3D10_FILL_SOLID;
965 rs_desc.CullMode = D3D10_CULL_BACK;
966 rs_desc.FrontCounterClockwise = FALSE;
967 rs_desc.DepthBias = 0;
968 rs_desc.DepthBiasClamp = 0.0f;
969 rs_desc.SlopeScaledDepthBias = 0.0f;
970 rs_desc.DepthClipEnable = TRUE;
971 rs_desc.ScissorEnable = TRUE;
972 rs_desc.MultisampleEnable = FALSE;
973 rs_desc.AntialiasedLineEnable = FALSE;
974 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->clear_rs)))
976 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
977 goto err;
980 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
982 WARN("Failed to get surface desc, hr %#x.\n", hr);
983 goto err;
986 render_target->pixel_size.width = surface_desc.Width;
987 render_target->pixel_size.height = surface_desc.Height;
988 render_target->transform = identity;
990 if (!d2d_clip_stack_init(&render_target->clip_stack))
992 WARN("Failed to initialize clip stack.\n");
993 hr = E_FAIL;
994 goto err;
997 render_target->dpi_x = desc->dpiX;
998 render_target->dpi_y = desc->dpiY;
1000 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
1002 render_target->dpi_x = 96.0f;
1003 render_target->dpi_y = 96.0f;
1006 return S_OK;
1008 err:
1009 if (render_target->view)
1010 ID3D10RenderTargetView_Release(render_target->view);
1011 if (render_target->clear_rs)
1012 ID3D10RasterizerState_Release(render_target->clear_rs);
1013 if (render_target->clear_ps)
1014 ID3D10PixelShader_Release(render_target->clear_ps);
1015 if (render_target->clear_vs)
1016 ID3D10VertexShader_Release(render_target->clear_vs);
1017 if (render_target->clear_vb)
1018 ID3D10Buffer_Release(render_target->clear_vb);
1019 if (render_target->clear_il)
1020 ID3D10InputLayout_Release(render_target->clear_il);
1021 if (render_target->stateblock)
1022 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
1023 if (render_target->device)
1024 ID3D10Device_Release(render_target->device);
1025 return hr;