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