Changeset 28475 in vbox for trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/buffer.c
- Timestamp:
- Apr 19, 2010 3:27:01 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/buffer.c
r25949 r28475 4 4 * Copyright 2004 Christian Costa 5 5 * Copyright 2005 Oliver Stieber 6 * Copyright 2007 Stefan Dösinger for CodeWeavers6 * Copyright 2007-2010 Stefan Dösinger for CodeWeavers 7 7 * Copyright 2009 Henri Verbeet for CodeWeavers 8 8 * … … 66 66 } 67 67 68 if(!offset && !size) 68 if(offset > This->resource.size || offset + size > This->resource.size) 69 { 70 WARN("Invalid range dirtified, marking entire buffer dirty\n"); 71 offset = 0; 72 size = This->resource.size; 73 } 74 else if(!offset && !size) 69 75 { 70 76 size = This->resource.size; … … 99 105 } 100 106 return FALSE; 107 } 108 109 /* Context activation is done by the caller */ 110 static void delete_gl_buffer(struct wined3d_buffer *This) 111 { 112 if(!This->buffer_object) return; 113 114 ENTER_GL(); 115 GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); 116 checkGLcall("glDeleteBuffersARB"); 117 LEAVE_GL(); 118 This->buffer_object = 0; 119 120 if(This->query) 121 { 122 wined3d_event_query_destroy(This->query); 123 This->query = NULL; 124 } 125 This->flags &= ~WINED3D_BUFFER_APPLESYNC; 101 126 } 102 127 … … 155 180 TRACE("Gl usage = GL_STREAM_DRAW_ARB\n"); 156 181 gl_usage = GL_STREAM_DRAW_ARB; 157 }158 else159 {160 TRACE("Gl usage = GL_DYNAMIC_DRAW_ARB\n");161 gl_usage = GL_DYNAMIC_DRAW_ARB;162 182 163 183 if(gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) … … 166 186 checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)"); 167 187 This->flags |= WINED3D_BUFFER_FLUSH; 168 } 188 189 GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); 190 checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)"); 191 This->flags |= WINED3D_BUFFER_APPLESYNC; 192 } 193 /* No setup is needed here for GL_ARB_map_buffer_range */ 194 } 195 else 196 { 197 TRACE("Gl usage = GL_DYNAMIC_DRAW_ARB\n"); 198 gl_usage = GL_DYNAMIC_DRAW_ARB; 169 199 } 170 200 … … 206 236 /* Clean up all vbo init, but continue because we can work without a vbo :-) */ 207 237 ERR("Failed to create a vertex buffer object. Continuing, but performance issues may occur\n"); 208 if (This->buffer_object) 209 { 210 ENTER_GL(); 211 GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); 212 LEAVE_GL(); 213 } 214 This->buffer_object = 0; 238 delete_gl_buffer(This); 215 239 buffer_clear_dirty_areas(This); 216 240 } … … 261 285 for (i = 0; i < attrib_size; ++i) 262 286 { 263 if (This->conversion_map[data + i] != conversion_type) 264 { 265 TRACE("Byte %ld in vertex changed\n", i + data); 266 TRACE("It was type %d, is %d now\n", This->conversion_map[data + i], conversion_type); 287 DWORD_PTR idx = (data + i) % This->stride; 288 if (This->conversion_map[idx] != conversion_type) 289 { 290 TRACE("Byte %ld in vertex changed\n", idx); 291 TRACE("It was type %d, is %d now\n", This->conversion_map[idx], conversion_type); 267 292 ret = TRUE; 268 This->conversion_map[ data + i] = conversion_type;293 This->conversion_map[idx] = conversion_type; 269 294 } 270 295 } … … 493 518 * the attributes that our current fixed function pipeline implementation cares for. 494 519 */ 495 BOOL support_d3dcolor = gl_info->supported[ EXT_VERTEX_ARRAY_BGRA];520 BOOL support_d3dcolor = gl_info->supported[ARB_VERTEX_ARRAY_BGRA]; 496 521 ret = buffer_check_attribute(This, si, WINED3D_FFP_POSITION, 497 522 TRUE, TRUE, FALSE, &stride_this_run, &float16_used) || ret; … … 598 623 599 624 /* Context activation is done by the caller. */ 600 const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset,GLuint *buffer_object)625 const BYTE *buffer_get_memory(IWineD3DBuffer *iface, GLuint *buffer_object) 601 626 { 602 627 struct wined3d_buffer *This = (struct wined3d_buffer *)iface; … … 612 637 { 613 638 *buffer_object = This->buffer_object; 614 return (const BYTE *)offset;615 } 616 } 617 return This->resource.allocatedMemory + offset;639 return NULL; 640 } 641 } 642 return This->resource.allocatedMemory; 618 643 } 619 644 else 620 645 { 621 return (const BYTE *)offset;646 return NULL; 622 647 } 623 648 } … … 694 719 } 695 720 696 ENTER_GL(); 697 GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); 698 checkGLcall("glDeleteBuffersARB"); 699 LEAVE_GL(); 700 This->buffer_object = 0; 721 delete_gl_buffer(This); 701 722 This->flags |= WINED3D_BUFFER_CREATEBO; /* Recreate the buffer object next load */ 702 723 buffer_clear_dirty_areas(This); … … 769 790 } 770 791 792 /* The caller provides a context and binds the buffer */ 793 static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const struct wined3d_gl_info *gl_info) 794 { 795 enum wined3d_event_query_result ret; 796 797 /* No fencing needs to be done if the app promises not to overwrite 798 * existing data */ 799 if(flags & WINED3DLOCK_NOOVERWRITE) return; 800 if(flags & WINED3DLOCK_DISCARD) 801 { 802 ENTER_GL(); 803 GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage)); 804 checkGLcall("glBufferDataARB\n"); 805 LEAVE_GL(); 806 return; 807 } 808 809 if(!This->query) 810 { 811 TRACE("Creating event query for buffer %p\n", This); 812 813 if (!wined3d_event_query_supported(gl_info)) 814 { 815 FIXME("Event queries not supported, dropping async buffer locks.\n"); 816 goto drop_query; 817 } 818 819 This->query = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->query)); 820 if (!This->query) 821 { 822 ERR("Failed to allocate event query memory, dropping async buffer locks.\n"); 823 goto drop_query; 824 } 825 826 /* Since we don't know about old draws a glFinish is needed once */ 827 wglFinish(); 828 return; 829 } 830 TRACE("Synchronizing buffer %p\n", This); 831 ret = wined3d_event_query_finish(This->query, This->resource.device); 832 switch(ret) 833 { 834 case WINED3D_EVENT_QUERY_NOT_STARTED: 835 case WINED3D_EVENT_QUERY_OK: 836 /* All done */ 837 return; 838 839 case WINED3D_EVENT_QUERY_WRONG_THREAD: 840 WARN("Cannot synchronize buffer lock due to a thread conflict\n"); 841 goto drop_query; 842 843 default: 844 ERR("wined3d_event_query_finish returned %u, dropping async buffer locks\n", ret); 845 goto drop_query; 846 } 847 848 drop_query: 849 if(This->query) 850 { 851 wined3d_event_query_destroy(This->query); 852 This->query = NULL; 853 } 854 855 wglFinish(); 856 ENTER_GL(); 857 GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)); 858 checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)"); 859 LEAVE_GL(); 860 This->flags &= ~WINED3D_BUFFER_APPLESYNC; 861 } 862 863 /* The caller provides a GL context */ 864 static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags) 865 { 866 BYTE *map; 867 UINT start = 0, len = 0; 868 869 ENTER_GL(); 870 GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); 871 checkGLcall("glBindBufferARB"); 872 if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) 873 { 874 GLbitfield mapflags; 875 mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; 876 if (flags & WINED3D_BUFFER_DISCARD) 877 { 878 mapflags |= GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT; 879 } 880 else if (flags & WINED3D_BUFFER_NOSYNC) 881 { 882 mapflags |= GL_MAP_UNSYNCHRONIZED_BIT; 883 } 884 map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, 885 This->resource.size, mapflags)); 886 checkGLcall("glMapBufferRange"); 887 } 888 else 889 { 890 if (This->flags & WINED3D_BUFFER_APPLESYNC) 891 { 892 DWORD syncflags = 0; 893 if (flags & WINED3D_BUFFER_DISCARD) syncflags |= WINED3DLOCK_DISCARD; 894 if (flags & WINED3D_BUFFER_NOSYNC) syncflags |= WINED3DLOCK_NOOVERWRITE; 895 LEAVE_GL(); 896 buffer_sync_apple(This, syncflags, gl_info); 897 ENTER_GL(); 898 } 899 map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB)); 900 checkGLcall("glMapBufferARB"); 901 } 902 if (!map) 903 { 904 LEAVE_GL(); 905 ERR("Failed to map opengl buffer\n"); 906 return; 907 } 908 909 while(This->modified_areas) 910 { 911 This->modified_areas--; 912 start = This->maps[This->modified_areas].offset; 913 len = This->maps[This->modified_areas].size; 914 915 memcpy(map + start, This->resource.allocatedMemory + start, len); 916 917 if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) 918 { 919 GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len)); 920 checkGLcall("glFlushMappedBufferRange"); 921 } 922 else if (This->flags & WINED3D_BUFFER_FLUSH) 923 { 924 GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len)); 925 checkGLcall("glFlushMappedBufferRangeAPPLE"); 926 } 927 } 928 GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); 929 checkGLcall("glUnmapBufferARB"); 930 LEAVE_GL(); 931 } 932 771 933 static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) 772 934 { … … 778 940 unsigned int i, j; 779 941 BYTE *data; 942 DWORD flags = This->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD); 780 943 781 944 TRACE("iface %p\n", iface); 945 This->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD); 782 946 783 947 context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); … … 840 1004 } 841 1005 buffer_check_buffer_object_size(This); 1006 1007 /* The declaration changed, reload the whole buffer */ 1008 WARN("Reloading buffer because of decl change\n"); 1009 buffer_clear_dirty_areas(This); 1010 if(!buffer_add_dirty_area(This, 0, 0)) 1011 { 1012 ERR("buffer_add_dirty_area failed, this is not expected\n"); 1013 return; 1014 } 1015 /* Avoid unfenced updates, we might overwrite more areas of the buffer than the application 1016 * cleared for unsynchronized updates 1017 */ 1018 flags = 0; 842 1019 } 843 1020 else … … 867 1044 } 868 1045 869 if (decl_changed)870 {871 /* The declaration changed, reload the whole buffer */872 WARN("Reloading buffer because of decl change\n");873 buffer_clear_dirty_areas(This);874 if(!buffer_add_dirty_area(This, 0, 0))875 {876 ERR("buffer_add_dirty_area failed, this is not expected\n");877 return;878 }879 }880 881 1046 if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) 882 1047 { … … 899 1064 } 900 1065 901 ENTER_GL(); 902 GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); 903 checkGLcall("glBindBufferARB"); 904 while(This->modified_areas) 905 { 906 This->modified_areas--; 907 start = This->maps[This->modified_areas].offset; 908 len = This->maps[This->modified_areas].size; 909 GL_EXTCALL(glBufferSubDataARB(This->buffer_type_hint, start, len, This->resource.allocatedMemory + start)); 910 checkGLcall("glBufferSubDataARB"); 911 } 912 LEAVE_GL(); 1066 buffer_direct_upload(This, context->gl_info, flags); 913 1067 914 1068 context_release(context); … … 1036 1190 /* IWineD3DBuffer methods */ 1037 1191 1192 static DWORD buffer_sanitize_flags(struct wined3d_buffer *buffer, DWORD flags) 1193 { 1194 /* Not all flags make sense together, but Windows never returns an error. Catch the 1195 * cases that could cause issues */ 1196 if(flags & WINED3DLOCK_READONLY) 1197 { 1198 if(flags & WINED3DLOCK_DISCARD) 1199 { 1200 WARN("WINED3DLOCK_READONLY combined with WINED3DLOCK_DISCARD, ignoring flags\n"); 1201 return 0; 1202 } 1203 if(flags & WINED3DLOCK_NOOVERWRITE) 1204 { 1205 WARN("WINED3DLOCK_READONLY combined with WINED3DLOCK_NOOVERWRITE, ignoring flags\n"); 1206 return 0; 1207 } 1208 } 1209 else if((flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE)) == (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE)) 1210 { 1211 WARN("WINED3DLOCK_DISCARD and WINED3DLOCK_NOOVERWRITE used together, ignoring\n"); 1212 return 0; 1213 } 1214 else if (flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE) && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC)) 1215 { 1216 WARN("DISCARD or NOOVERWRITE lock on non-dynamic buffer, ignoring\n"); 1217 return 0; 1218 } 1219 1220 return flags; 1221 } 1222 1223 static GLbitfield buffer_gl_map_flags(DWORD d3d_flags) 1224 { 1225 GLbitfield ret = 0; 1226 1227 if (!(d3d_flags & WINED3DLOCK_READONLY)) ret = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; 1228 1229 if (d3d_flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE)) 1230 { 1231 if(d3d_flags & WINED3DLOCK_DISCARD) ret |= GL_MAP_INVALIDATE_BUFFER_BIT; 1232 ret |= GL_MAP_UNSYNCHRONIZED_BIT; 1233 } 1234 else 1235 { 1236 ret |= GL_MAP_READ_BIT; 1237 } 1238 1239 return ret; 1240 } 1241 1038 1242 static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, UINT size, BYTE **data, DWORD flags) 1039 1243 { 1040 1244 struct wined3d_buffer *This = (struct wined3d_buffer *)iface; 1041 1245 LONG count; 1246 BOOL dirty = buffer_is_dirty(This); 1042 1247 1043 1248 TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags); 1044 1249 1045 if (!buffer_add_dirty_area(This, offset, size)) return E_OUTOFMEMORY; 1250 flags = buffer_sanitize_flags(This, flags); 1251 if (!(flags & WINED3DLOCK_READONLY)) 1252 { 1253 if (!buffer_add_dirty_area(This, offset, size)) return E_OUTOFMEMORY; 1254 } 1046 1255 1047 1256 count = InterlockedIncrement(&This->lock_count); 1048 1257 1049 if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object) 1050 { 1051 if(count == 1) 1052 { 1053 IWineD3DDeviceImpl *device = This->resource.device; 1054 struct wined3d_context *context; 1055 1056 if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) 1057 { 1058 IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); 1059 } 1060 1061 context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); 1062 ENTER_GL(); 1063 GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); 1064 This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); 1065 LEAVE_GL(); 1066 context_release(context); 1258 if (This->buffer_object) 1259 { 1260 if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) 1261 { 1262 if(count == 1) 1263 { 1264 IWineD3DDeviceImpl *device = This->resource.device; 1265 struct wined3d_context *context; 1266 const struct wined3d_gl_info *gl_info; 1267 1268 if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) 1269 { 1270 IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); 1271 } 1272 1273 context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); 1274 gl_info = context->gl_info; 1275 ENTER_GL(); 1276 GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); 1277 1278 if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) 1279 { 1280 GLbitfield mapflags = buffer_gl_map_flags(flags); 1281 This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, 1282 This->resource.size, mapflags)); 1283 checkGLcall("glMapBufferRange"); 1284 } 1285 else 1286 { 1287 if(This->flags & WINED3D_BUFFER_APPLESYNC) 1288 { 1289 LEAVE_GL(); 1290 buffer_sync_apple(This, flags, gl_info); 1291 ENTER_GL(); 1292 } 1293 This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); 1294 checkGLcall("glMapBufferARB"); 1295 } 1296 LEAVE_GL(); 1297 1298 if (((DWORD_PTR) This->resource.allocatedMemory) & (RESOURCE_ALIGNMENT - 1)) 1299 { 1300 WARN("Pointer %p is not %u byte aligned, falling back to double buffered operation\n", 1301 This->resource.allocatedMemory, RESOURCE_ALIGNMENT); 1302 1303 ENTER_GL(); 1304 GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); 1305 checkGLcall("glUnmapBufferARB"); 1306 LEAVE_GL(); 1307 This->resource.allocatedMemory = NULL; 1308 1309 buffer_get_sysmem(This); 1310 TRACE("New pointer is %p\n", This->resource.allocatedMemory); 1311 } 1312 context_release(context); 1313 } 1314 } 1315 else 1316 { 1317 if (dirty) 1318 { 1319 if (This->flags & WINED3D_BUFFER_NOSYNC && !(flags & WINED3DLOCK_NOOVERWRITE)) 1320 { 1321 This->flags &= ~WINED3D_BUFFER_NOSYNC; 1322 } 1323 } 1324 else if(flags & WINED3DLOCK_NOOVERWRITE) 1325 { 1326 This->flags |= WINED3D_BUFFER_NOSYNC; 1327 } 1328 1329 if (flags & WINED3DLOCK_DISCARD) 1330 { 1331 This->flags |= WINED3D_BUFFER_DISCARD; 1332 } 1067 1333 } 1068 1334 } … … 1103 1369 { 1104 1370 IWineD3DDeviceImpl *device = This->resource.device; 1371 const struct wined3d_gl_info *gl_info; 1105 1372 struct wined3d_context *context; 1106 1373 … … 1111 1378 1112 1379 context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); 1380 gl_info = context->gl_info; 1113 1381 ENTER_GL(); 1114 1382 GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); 1115 1383 1116 if(This->flags & WINED3D_BUFFER_FLUSH) 1384 if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) 1385 { 1386 for(i = 0; i < This->modified_areas; i++) 1387 { 1388 GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, 1389 This->maps[i].offset, 1390 This->maps[i].size)); 1391 checkGLcall("glFlushMappedBufferRange"); 1392 } 1393 } 1394 else if (This->flags & WINED3D_BUFFER_FLUSH) 1117 1395 { 1118 1396 for(i = 0; i < This->modified_areas; i++) … … 1181 1459 const char *data, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) 1182 1460 { 1183 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &device->adapter->gl_info);1461 const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, &device->adapter->gl_info); 1184 1462 HRESULT hr; 1185 1463 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; … … 1206 1484 debug_d3dformat(buffer->resource.format_desc->format), buffer->resource.allocatedMemory, buffer); 1207 1485 1208 /* TODO: GL_ARB_map_buffer_range */ 1209 dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]; 1486 dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE]; 1210 1487 1211 1488 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
Note:
See TracChangeset
for help on using the changeset viewer.