intel: Begin adding pipeline support.
diff --git a/icd/intel/pipeline.c b/icd/intel/pipeline.c
new file mode 100644
index 0000000..ca61557
--- /dev/null
+++ b/icd/intel/pipeline.c
@@ -0,0 +1,313 @@
+/*
+ * XGL
+ *
+ * Copyright (C) 2014 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "pipeline.h"
+#include "brw_defines.h"
+
+static XGL_RESULT intelPipelineIAState(struct intel_dev *dev, struct intel_pipeline *pipeline,
+ const XGL_PIPELINE_IA_STATE_CREATE_INFO* ia_state)
+{
+ if (ia_state->provokingVertex == XGL_PROVOKING_VERTEX_FIRST) {
+ pipeline->provoking_vertex_tri = BRW_PROVOKING_VERTEX_0;
+ pipeline->provoking_vertex_trifan = BRW_PROVOKING_VERTEX_1;
+ pipeline->provoking_vertex_line = BRW_PROVOKING_VERTEX_0;
+ } else {
+ pipeline->provoking_vertex_tri = BRW_PROVOKING_VERTEX_2;
+ pipeline->provoking_vertex_trifan = BRW_PROVOKING_VERTEX_2;
+ pipeline->provoking_vertex_line = BRW_PROVOKING_VERTEX_1;
+ }
+
+ switch (ia_state->topology) {
+ case XGL_TOPOLOGY_POINT_LIST:
+ pipeline->prim_type = _3DPRIM_POINTLIST;
+ break;
+ case XGL_TOPOLOGY_LINE_LIST:
+ pipeline->prim_type = _3DPRIM_LINELIST;
+ break;
+ case XGL_TOPOLOGY_LINE_STRIP:
+ pipeline->prim_type = _3DPRIM_LINESTRIP;
+ break;
+ case XGL_TOPOLOGY_TRIANGLE_LIST:
+ pipeline->prim_type = _3DPRIM_TRILIST;
+ break;
+ case XGL_TOPOLOGY_TRIANGLE_STRIP:
+ pipeline->prim_type = _3DPRIM_TRISTRIP;
+ break;
+ case XGL_TOPOLOGY_RECT_LIST:
+ /*
+ * TODO: Rect lists are special in XGL, do we need to do
+ * something special here?
+ * XGL Guide:
+ * The rectangle list is a special geometry primitive type
+ * that can be used for implementing post-processing techniques
+ * or efficient copy operations. There are some special limitations
+ * for rectangle primitives. They cannot be clipped, must
+ * be axis aligned and cannot have depth gradient.
+ * Failure to comply with these restrictions results in
+ * undefined rendering results.
+ */
+ pipeline->prim_type = _3DPRIM_RECTLIST;
+ break;
+ case XGL_TOPOLOGY_QUAD_LIST:
+ pipeline->prim_type = _3DPRIM_QUADLIST;
+ break;
+ case XGL_TOPOLOGY_QUAD_STRIP:
+ pipeline->prim_type = _3DPRIM_QUADSTRIP;
+ break;
+ case XGL_TOPOLOGY_LINE_LIST_ADJ:
+ // TODO: implement
+ break;
+ case XGL_TOPOLOGY_LINE_STRIP_ADJ:
+ // TODO: implement
+ break;
+ case XGL_TOPOLOGY_TRIANGLE_LIST_ADJ:
+ // TODO: implement
+ break;
+ case XGL_TOPOLOGY_TRIANGLE_STRIP_ADJ:
+ // TODO: implement
+ break;
+ case XGL_TOPOLOGY_PATCH:
+ // TODO: implement something here
+ break;
+ default:
+ return XGL_ERROR_BAD_PIPELINE_DATA;
+ }
+
+ if (ia_state->primitiveRestartEnable) {
+ pipeline->primitive_restart = true;
+ pipeline->primitive_restart_index = ia_state->primitiveRestartIndex;
+ } else {
+ pipeline->primitive_restart = false;
+ }
+
+ if (ia_state->disableVertexReuse) {
+ // TODO: What do we do to disable vertex reuse?
+ }
+
+ return XGL_SUCCESS;
+}
+
+static XGL_RESULT intelPipelineRSState(struct intel_dev *dev, struct intel_pipeline *pipeline,
+ const XGL_PIPELINE_RS_STATE_CREATE_INFO* rs_state)
+{
+ pipeline->depthClipEnable = rs_state->depthClipEnable;
+ pipeline->rasterizerDiscardEnable = rs_state->rasterizerDiscardEnable;
+ pipeline->pointSize = rs_state->pointSize;
+ return XGL_SUCCESS;
+}
+
+static void intelPipelineDestroy(struct intel_obj *obj)
+{
+ struct intel_pipeline *pipeline = intel_pipeline_from_obj(obj);
+
+ intel_base_destroy(&pipeline->obj.base);
+}
+
+XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
+ XGL_DEVICE device,
+ const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
+ XGL_PIPELINE* pPipeline)
+{
+ union {
+ const void *ptr;
+ const struct {
+ XGL_STRUCTURE_TYPE struct_type;
+ XGL_VOID *next;
+ } *header;
+ const XGL_GRAPHICS_PIPELINE_CREATE_INFO* graphics_pipeline;
+ const XGL_PIPELINE_IA_STATE_CREATE_INFO* ia_state;
+ const XGL_PIPELINE_DB_STATE_CREATE_INFO* db_state;
+ const XGL_PIPELINE_CB_STATE* cb_state;
+ const XGL_PIPELINE_RS_STATE_CREATE_INFO* rs_state;
+ const XGL_PIPELINE_TESS_STATE_CREATE_INFO* tess_state;
+ const XGL_PIPELINE_SHADER_STAGE_CREATE_INFO* shader_state;
+ } info = { .ptr = pCreateInfo };
+ struct intel_dev *dev = intel_dev(device);
+ struct intel_pipeline *pipeline;
+ XGL_RESULT result;
+
+ pipeline = (struct intel_pipeline *) intel_base_create(dev, sizeof(*pipeline),
+ dev->base.dbg, XGL_DBG_OBJECT_GRAPHICS_PIPELINE, pCreateInfo, 0);
+ if (!pipeline) {
+ return XGL_ERROR_OUT_OF_MEMORY;
+ }
+
+ pipeline->dev = dev;
+ pipeline->obj.destroy = intelPipelineDestroy;
+
+ do {
+ result = XGL_SUCCESS;
+
+ switch (info.header->struct_type) {
+ case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
+ // TODO: Should not see Compute Pipeline structs processing CreateGraphicsPipeline
+ return XGL_ERROR_BAD_PIPELINE_DATA;
+
+ case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
+ if (info.graphics_pipeline->flags & XGL_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT) {
+ // TODO: process disable optimization.
+ }
+ break;
+
+ case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
+ result = intelPipelineIAState(dev, pipeline, info.ia_state);
+ break;
+
+ case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
+ pipeline->db_format = info.db_state->format;
+ break;
+
+ case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
+ pipeline->cb_state = *info.cb_state;
+ break;
+
+ case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
+ result = intelPipelineRSState(dev, pipeline, info.rs_state);
+ break;
+
+ case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
+ pipeline->tess_state = *info.tess_state;
+ break;
+
+ case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
+ switch (info.shader_state->shader.stage) {
+ case XGL_SHADER_STAGE_VERTEX:
+ pipeline->vs = info.shader_state->shader;
+ pipeline->active_shaders |= SHADER_VERTEX_FLAG;
+ break;
+ case XGL_SHADER_STAGE_GEOMETRY:
+ pipeline->gs = info.shader_state->shader;
+ pipeline->active_shaders |= SHADER_GEOMETRY_FLAG;
+ break;
+ case XGL_SHADER_STAGE_FRAGMENT:
+ pipeline->fs = info.shader_state->shader;
+ pipeline->active_shaders |= SHADER_FRAGMENT_FLAG;
+ break;
+ case XGL_SHADER_STAGE_TESS_CONTROL:
+ pipeline->tess_control = info.shader_state->shader;
+ pipeline->active_shaders |= SHADER_TESS_CONTROL_FLAG;
+ break;
+ case XGL_SHADER_STAGE_TESS_EVALUATION:
+ pipeline->tess_eval = info.shader_state->shader;
+ pipeline->active_shaders |= SHADER_TESS_EVAL_FLAG;
+ break;
+ case XGL_SHADER_STAGE_COMPUTE:
+ pipeline->compute = info.shader_state->shader;
+ pipeline->active_shaders |= SHADER_COMPUTE_FLAG;
+ break;
+ default:
+ // TODO: Log debug message
+ result = XGL_ERROR_BAD_PIPELINE_DATA;
+ goto error_exit;
+ }
+ break;
+
+ default:
+ // TODO: Log debug message
+ result = XGL_ERROR_BAD_PIPELINE_DATA;
+ goto error_exit;
+ }
+
+ if (result != XGL_SUCCESS) {
+ // TODO: What needs to happen if pipeline build fails?
+ goto error_exit;
+ }
+ info.ptr = info.header->next;
+ } while (info.ptr != NULL);
+
+ /*
+ * Validate required elements
+ */
+ if (!(pipeline->active_shaders & SHADER_VERTEX_FLAG)) {
+ // TODO: Log debug message: Vertex Shader required.
+ result = XGL_ERROR_BAD_PIPELINE_DATA;
+ goto error_exit;
+ }
+
+ /*
+ * Tessalation control and evaluation have to both have a shader defined or
+ * neither should have a shader defined.
+ */
+ if (((pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) == 0) !=
+ ((pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) == 0) ) {
+ // TODO: Log debug message: Both Tess control and Tess eval are required to use tessalation
+ result = XGL_ERROR_BAD_PIPELINE_DATA;
+ goto error_exit;
+ }
+
+ if ((pipeline->active_shaders & SHADER_COMPUTE_FLAG) &&
+ (pipeline->active_shaders & (SHADER_VERTEX_FLAG | SHADER_TESS_CONTROL_FLAG |
+ SHADER_TESS_EVAL_FLAG | SHADER_GEOMETRY_FLAG |
+ SHADER_FRAGMENT_FLAG))) {
+ // TODO: Log debug message: Can only specify compute shader when doing compute
+ result = XGL_ERROR_BAD_PIPELINE_DATA;
+ goto error_exit;
+ }
+
+ /*
+ * Now compile everything into a pipeline object ready for the HW.
+ */
+
+ *pPipeline = pipeline;
+
+ return XGL_SUCCESS;
+
+error_exit:
+ intel_base_destroy(&pipeline->obj.base);
+ return result;
+}
+
+XGL_RESULT XGLAPI intelCreateComputePipeline(
+ XGL_DEVICE device,
+ const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
+ XGL_PIPELINE* pPipeline)
+{
+ return XGL_ERROR_UNAVAILABLE;
+}
+
+XGL_RESULT XGLAPI intelStorePipeline(
+ XGL_PIPELINE pipeline,
+ XGL_SIZE* pDataSize,
+ XGL_VOID* pData)
+{
+ return XGL_ERROR_UNAVAILABLE;
+}
+
+XGL_RESULT XGLAPI intelLoadPipeline(
+ XGL_DEVICE device,
+ XGL_SIZE dataSize,
+ const XGL_VOID* pData,
+ XGL_PIPELINE* pPipeline)
+{
+ return XGL_ERROR_UNAVAILABLE;
+}
+
+XGL_RESULT XGLAPI intelCreatePipelineDelta(
+ XGL_DEVICE device,
+ XGL_PIPELINE p1,
+ XGL_PIPELINE p2,
+ XGL_PIPELINE_DELTA* delta)
+{
+ return XGL_ERROR_UNAVAILABLE;
+}