1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
8
9 #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
10
11 #include "libANGLE/Buffer.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/VertexAttribute.h"
14 #include "libANGLE/renderer/d3d/BufferD3D.h"
15 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
16 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
17 #include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
18
19 namespace rx
20 {
21
VertexBuffer9(Renderer9 * renderer)22 VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
23 {
24 mVertexBuffer = nullptr;
25 mBufferSize = 0;
26 mDynamicUsage = false;
27 }
28
~VertexBuffer9()29 VertexBuffer9::~VertexBuffer9()
30 {
31 SafeRelease(mVertexBuffer);
32 }
33
initialize(const gl::Context * context,unsigned int size,bool dynamicUsage)34 angle::Result VertexBuffer9::initialize(const gl::Context *context,
35 unsigned int size,
36 bool dynamicUsage)
37 {
38 SafeRelease(mVertexBuffer);
39
40 updateSerial();
41
42 if (size > 0)
43 {
44 DWORD flags = D3DUSAGE_WRITEONLY;
45 if (dynamicUsage)
46 {
47 flags |= D3DUSAGE_DYNAMIC;
48 }
49
50 HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
51 ANGLE_TRY_HR(GetImplAs<Context9>(context), result,
52 "Failed to allocate internal vertex buffer");
53 }
54
55 mBufferSize = size;
56 mDynamicUsage = dynamicUsage;
57 return angle::Result::Continue;
58 }
59
storeVertexAttributes(const gl::Context * context,const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,gl::VertexAttribType currentValueType,GLint start,size_t count,GLsizei instances,unsigned int offset,const uint8_t * sourceData)60 angle::Result VertexBuffer9::storeVertexAttributes(const gl::Context *context,
61 const gl::VertexAttribute &attrib,
62 const gl::VertexBinding &binding,
63 gl::VertexAttribType currentValueType,
64 GLint start,
65 size_t count,
66 GLsizei instances,
67 unsigned int offset,
68 const uint8_t *sourceData)
69 {
70 ASSERT(mVertexBuffer);
71
72 size_t inputStride = gl::ComputeVertexAttributeStride(attrib, binding);
73 size_t elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
74
75 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
76
77 uint8_t *mapPtr = nullptr;
78
79 unsigned int mapSize = 0;
80 ANGLE_TRY(
81 mRenderer->getVertexSpaceRequired(context, attrib, binding, count, instances, 0, &mapSize));
82
83 HRESULT result =
84 mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void **>(&mapPtr), lockFlags);
85 ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to lock internal vertex buffer");
86
87 const uint8_t *input = sourceData;
88
89 if (instances == 0 || binding.getDivisor() == 0)
90 {
91 input += inputStride * start;
92 }
93
94 angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, currentValueType);
95 const d3d9::VertexFormat &d3dVertexInfo =
96 d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatID);
97 bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
98
99 if (!needsConversion && inputStride == elementSize)
100 {
101 size_t copySize = count * inputStride;
102 memcpy(mapPtr, input, copySize);
103 }
104 else
105 {
106 d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
107 }
108
109 mVertexBuffer->Unlock();
110
111 return angle::Result::Continue;
112 }
113
getBufferSize() const114 unsigned int VertexBuffer9::getBufferSize() const
115 {
116 return mBufferSize;
117 }
118
setBufferSize(const gl::Context * context,unsigned int size)119 angle::Result VertexBuffer9::setBufferSize(const gl::Context *context, unsigned int size)
120 {
121 if (size > mBufferSize)
122 {
123 return initialize(context, size, mDynamicUsage);
124 }
125 else
126 {
127 return angle::Result::Continue;
128 }
129 }
130
discard(const gl::Context * context)131 angle::Result VertexBuffer9::discard(const gl::Context *context)
132 {
133 ASSERT(mVertexBuffer);
134
135 void *mock;
136 HRESULT result;
137
138 Context9 *context9 = GetImplAs<Context9>(context);
139
140 result = mVertexBuffer->Lock(0, 1, &mock, D3DLOCK_DISCARD);
141 ANGLE_TRY_HR(context9, result, "Failed to lock internal vertex buffer for discarding");
142
143 result = mVertexBuffer->Unlock();
144 ANGLE_TRY_HR(context9, result, "Failed to unlock internal vertex buffer for discarding");
145
146 return angle::Result::Continue;
147 }
148
getBuffer() const149 IDirect3DVertexBuffer9 *VertexBuffer9::getBuffer() const
150 {
151 return mVertexBuffer;
152 }
153 } // namespace rx
154