mirror of https://github.com/axmolengine/axmol.git
Update thirdparty libs
This commit is contained in:
parent
1eb3675b48
commit
831ad310f5
|
@ -6,7 +6,7 @@
|
|||
|
||||
## astc
|
||||
- [![Upstream](https://img.shields.io/github/v/release/ARM-software/astc-encoder?label=Upstream)](https://github.com/ARM-software/astc-encoder)
|
||||
- Version: 4.1.0
|
||||
- Version: 4.3.0
|
||||
- License: Apache-2.0
|
||||
|
||||
## Box2D
|
||||
|
@ -67,12 +67,12 @@
|
|||
|
||||
## Glad
|
||||
- [![Upstream](https://img.shields.io/github/v/tag/Dav1dde/glad?label=Upstream)](https://github.com/Dav1dde/glad)
|
||||
- Version: 2.0.2
|
||||
- Version: 2.0.3
|
||||
- License: MIT
|
||||
|
||||
## glfw
|
||||
- [![Upstream](https://img.shields.io/github/v/release/glfw/glfw?label=Upstream)](https://github.com/glfw/glfw)
|
||||
- Version: git df8d7bc on 31 Dec 2021 (4398)
|
||||
- Version: git 57cbded on Dec 16, 2022 (4609)
|
||||
- License: zlib
|
||||
|
||||
## glsl-optimizer (Apple Metal Render backend only)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2020-2022 Arm Limited
|
||||
// Copyright 2020-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -74,7 +74,7 @@
|
|||
*
|
||||
* The codec supports compressing single images, which can be either 2D images or volumetric 3D
|
||||
* images. Calling code is responsible for any handling of aggregate types, such as mipmap chains,
|
||||
* texture arrays, or sliced 3D textures
|
||||
* texture arrays, or sliced 3D textures.
|
||||
*
|
||||
* Images are passed in as an astcenc_image structure. Inputs can be either 8-bit unorm, 16-bit
|
||||
* half-float, or 32-bit float, as indicated by the data_type field.
|
||||
|
@ -241,6 +241,9 @@ static const float ASTCENC_PRE_MEDIUM = 60.0f;
|
|||
/** @brief The thorough quality search preset. */
|
||||
static const float ASTCENC_PRE_THOROUGH = 98.0f;
|
||||
|
||||
/** @brief The thorough quality search preset. */
|
||||
static const float ASTCENC_PRE_VERYTHOROUGH = 99.0f;
|
||||
|
||||
/** @brief The exhaustive, highest quality, search preset. */
|
||||
static const float ASTCENC_PRE_EXHAUSTIVE = 100.0f;
|
||||
|
||||
|
@ -303,14 +306,6 @@ enum astcenc_type
|
|||
*/
|
||||
static const unsigned int ASTCENC_FLG_MAP_NORMAL = 1 << 0;
|
||||
|
||||
/**
|
||||
* @brief Enable mask map compression.
|
||||
*
|
||||
* Input data will be treated a multi-layer mask map, where is is desirable for the color components
|
||||
* to be treated independently for the purposes of error analysis.
|
||||
*/
|
||||
static const unsigned int ASTCENC_FLG_MAP_MASK = 1 << 1;
|
||||
|
||||
/**
|
||||
* @brief Enable alpha weighting.
|
||||
*
|
||||
|
@ -373,7 +368,6 @@ static const unsigned int ASTCENC_FLG_MAP_RGBM = 1 << 6;
|
|||
* @brief The bit mask of all valid flags.
|
||||
*/
|
||||
static const unsigned int ASTCENC_ALL_FLAGS =
|
||||
ASTCENC_FLG_MAP_MASK |
|
||||
ASTCENC_FLG_MAP_NORMAL |
|
||||
ASTCENC_FLG_MAP_RGBM |
|
||||
ASTCENC_FLG_USE_ALPHA_WEIGHT |
|
||||
|
@ -440,11 +434,25 @@ struct astcenc_config
|
|||
unsigned int tune_partition_count_limit;
|
||||
|
||||
/**
|
||||
* @brief The maximum number of partitions searched (-partitionindexlimit).
|
||||
* @brief The maximum number of partitions searched (-2partitionindexlimit).
|
||||
*
|
||||
* Valid values are between 1 and 1024.
|
||||
*/
|
||||
unsigned int tune_partition_index_limit;
|
||||
unsigned int tune_2partition_index_limit;
|
||||
|
||||
/**
|
||||
* @brief The maximum number of partitions searched (-3partitionindexlimit).
|
||||
*
|
||||
* Valid values are between 1 and 1024.
|
||||
*/
|
||||
unsigned int tune_3partition_index_limit;
|
||||
|
||||
/**
|
||||
* @brief The maximum number of partitions searched (-4partitionindexlimit).
|
||||
*
|
||||
* Valid values are between 1 and 1024.
|
||||
*/
|
||||
unsigned int tune_4partition_index_limit;
|
||||
|
||||
/**
|
||||
* @brief The maximum centile for block modes searched (-blockmodelimit).
|
||||
|
@ -468,6 +476,27 @@ struct astcenc_config
|
|||
*/
|
||||
unsigned int tune_candidate_limit;
|
||||
|
||||
/**
|
||||
* @brief The number of trial partitionings per search (-2partitioncandidatelimit).
|
||||
*
|
||||
* Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES.
|
||||
*/
|
||||
unsigned int tune_2partitioning_candidate_limit;
|
||||
|
||||
/**
|
||||
* @brief The number of trial partitionings per search (-3partitioncandidatelimit).
|
||||
*
|
||||
* Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES.
|
||||
*/
|
||||
unsigned int tune_3partitioning_candidate_limit;
|
||||
|
||||
/**
|
||||
* @brief The number of trial partitionings per search (-4partitioncandidatelimit).
|
||||
*
|
||||
* Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES.
|
||||
*/
|
||||
unsigned int tune_4partitioning_candidate_limit;
|
||||
|
||||
/**
|
||||
* @brief The dB threshold for stopping block search (-dblimit).
|
||||
*
|
||||
|
@ -476,25 +505,15 @@ struct astcenc_config
|
|||
float tune_db_limit;
|
||||
|
||||
/**
|
||||
* @brief The amount of overshoot needed to early-out mode 0 fast path.
|
||||
* @brief The amount of MSE overshoot needed to early-out trials.
|
||||
*
|
||||
* We have a fast-path for mode 0 (1 partition, 1 plane) which uses only essential block modes
|
||||
* as an initial search. This can short-cut compression for simple blocks, but to avoid
|
||||
* short-cutting too much we force this to overshoot the MSE threshold needed to hit the
|
||||
* block-local db_limit e.g. 1.0 = no overshoot, 2.0 = need half the error to trigger.
|
||||
*/
|
||||
float tune_mode0_mse_overshoot;
|
||||
|
||||
/**
|
||||
* @brief The amount of overshoot needed to early-out refinement.
|
||||
* The first early-out is for 1 partition, 1 plane trials, where we try a minimal encode using
|
||||
* the high probability block modes. This can short-cut compression for simple blocks.
|
||||
*
|
||||
* The codec will refine block candidates iteratively to improve the encoding, based on the
|
||||
* @c tune_refinement_limit count. Earlier implementations will use all refinement iterations,
|
||||
* even if the target threshold is reached. This tuning parameter allows an early out, but with
|
||||
* an overshoot MSE threshold. Setting this to 1.0 will early-out as soon as the target is hit,
|
||||
* but does reduce image quality vs the default behavior of over-refinement.
|
||||
* The second early-out is for refinement trials, where we can exit refinement once quality is
|
||||
* reached.
|
||||
*/
|
||||
float tune_refinement_mse_overshoot;
|
||||
float tune_mse_overshoot;
|
||||
|
||||
/**
|
||||
* @brief The threshold for skipping 3.1/4.1 trials (-2partitionlimitfactor).
|
||||
|
@ -517,11 +536,6 @@ struct astcenc_config
|
|||
*/
|
||||
float tune_2_plane_early_out_limit_correlation;
|
||||
|
||||
/**
|
||||
* @brief The threshold below which (inclusive) we stop testing low/high/low+high cutoffs.
|
||||
*/
|
||||
unsigned int tune_low_weight_count_limit;
|
||||
|
||||
#if defined(ASTCENC_DIAGNOSTICS)
|
||||
/**
|
||||
* @brief The path to save the diagnostic trace data to.
|
||||
|
|
|
@ -390,8 +390,6 @@ void compute_avgs_and_dirs_4_comp(
|
|||
const image_block& blk,
|
||||
partition_metrics pm[BLOCK_MAX_PARTITIONS]
|
||||
) {
|
||||
float texel_weight = hadd_s(blk.channel_weight) / 4.0f;
|
||||
|
||||
int partition_count = pi.partition_count;
|
||||
promise(partition_count > 0);
|
||||
|
||||
|
@ -434,11 +432,6 @@ void compute_avgs_and_dirs_4_comp(
|
|||
sum_wp += select(zero, texel_datum, tdm3);
|
||||
}
|
||||
|
||||
sum_xp = sum_xp * texel_weight;
|
||||
sum_yp = sum_yp * texel_weight;
|
||||
sum_zp = sum_zp * texel_weight;
|
||||
sum_wp = sum_wp * texel_weight;
|
||||
|
||||
vfloat4 prod_xp = dot(sum_xp, sum_xp);
|
||||
vfloat4 prod_yp = dot(sum_yp, sum_yp);
|
||||
vfloat4 prod_zp = dot(sum_zp, sum_zp);
|
||||
|
@ -473,8 +466,6 @@ void compute_avgs_and_dirs_3_comp(
|
|||
vfloat4 partition_averages[BLOCK_MAX_PARTITIONS];
|
||||
compute_partition_averages_rgba(pi, blk, partition_averages);
|
||||
|
||||
float texel_weight = hadd_s(blk.channel_weight.swz<0, 1, 2>());
|
||||
|
||||
const float* data_vr = blk.data_r;
|
||||
const float* data_vg = blk.data_g;
|
||||
const float* data_vb = blk.data_b;
|
||||
|
@ -482,8 +473,6 @@ void compute_avgs_and_dirs_3_comp(
|
|||
// TODO: Data-driven permute would be useful to avoid this ...
|
||||
if (omitted_component == 0)
|
||||
{
|
||||
texel_weight = hadd_s(blk.channel_weight.swz<1, 2, 3>());
|
||||
|
||||
partition_averages[0] = partition_averages[0].swz<1, 2, 3>();
|
||||
partition_averages[1] = partition_averages[1].swz<1, 2, 3>();
|
||||
partition_averages[2] = partition_averages[2].swz<1, 2, 3>();
|
||||
|
@ -495,8 +484,6 @@ void compute_avgs_and_dirs_3_comp(
|
|||
}
|
||||
else if (omitted_component == 1)
|
||||
{
|
||||
texel_weight = hadd_s(blk.channel_weight.swz<0, 2, 3>());
|
||||
|
||||
partition_averages[0] = partition_averages[0].swz<0, 2, 3>();
|
||||
partition_averages[1] = partition_averages[1].swz<0, 2, 3>();
|
||||
partition_averages[2] = partition_averages[2].swz<0, 2, 3>();
|
||||
|
@ -507,8 +494,6 @@ void compute_avgs_and_dirs_3_comp(
|
|||
}
|
||||
else if (omitted_component == 2)
|
||||
{
|
||||
texel_weight = hadd_s(blk.channel_weight.swz<0, 1, 3>());
|
||||
|
||||
partition_averages[0] = partition_averages[0].swz<0, 1, 3>();
|
||||
partition_averages[1] = partition_averages[1].swz<0, 1, 3>();
|
||||
partition_averages[2] = partition_averages[2].swz<0, 1, 3>();
|
||||
|
@ -524,8 +509,6 @@ void compute_avgs_and_dirs_3_comp(
|
|||
partition_averages[3] = partition_averages[3].swz<0, 1, 2>();
|
||||
}
|
||||
|
||||
texel_weight = texel_weight * (1.0f / 3.0f);
|
||||
|
||||
unsigned int partition_count = pi.partition_count;
|
||||
promise(partition_count > 0);
|
||||
|
||||
|
@ -563,10 +546,6 @@ void compute_avgs_and_dirs_3_comp(
|
|||
sum_zp += select(zero, texel_datum, tdm2);
|
||||
}
|
||||
|
||||
sum_xp = sum_xp * texel_weight;
|
||||
sum_yp = sum_yp * texel_weight;
|
||||
sum_zp = sum_zp * texel_weight;
|
||||
|
||||
vfloat4 prod_xp = dot(sum_xp, sum_xp);
|
||||
vfloat4 prod_yp = dot(sum_yp, sum_yp);
|
||||
vfloat4 prod_zp = dot(sum_zp, sum_zp);
|
||||
|
@ -591,8 +570,6 @@ void compute_avgs_and_dirs_3_comp_rgb(
|
|||
const image_block& blk,
|
||||
partition_metrics pm[BLOCK_MAX_PARTITIONS]
|
||||
) {
|
||||
float texel_weight = hadd_s(blk.channel_weight.swz<0, 1, 2>()) * (1.0f / 3.0f);
|
||||
|
||||
unsigned int partition_count = pi.partition_count;
|
||||
promise(partition_count > 0);
|
||||
|
||||
|
@ -632,10 +609,6 @@ void compute_avgs_and_dirs_3_comp_rgb(
|
|||
sum_zp += select(zero, texel_datum, tdm2);
|
||||
}
|
||||
|
||||
sum_xp = sum_xp * texel_weight;
|
||||
sum_yp = sum_yp * texel_weight;
|
||||
sum_zp = sum_zp * texel_weight;
|
||||
|
||||
vfloat4 prod_xp = dot(sum_xp, sum_xp);
|
||||
vfloat4 prod_yp = dot(sum_yp, sum_yp);
|
||||
vfloat4 prod_zp = dot(sum_zp, sum_zp);
|
||||
|
@ -662,7 +635,6 @@ void compute_avgs_and_dirs_2_comp(
|
|||
unsigned int component2,
|
||||
partition_metrics pm[BLOCK_MAX_PARTITIONS]
|
||||
) {
|
||||
float texel_weight;
|
||||
vfloat4 average;
|
||||
|
||||
const float* data_vr = nullptr;
|
||||
|
@ -670,7 +642,6 @@ void compute_avgs_and_dirs_2_comp(
|
|||
|
||||
if (component1 == 0 && component2 == 1)
|
||||
{
|
||||
texel_weight = hadd_s(blk.channel_weight.swz<0, 1>()) / 2.0f;
|
||||
average = blk.data_mean.swz<0, 1>();
|
||||
|
||||
data_vr = blk.data_r;
|
||||
|
@ -678,7 +649,6 @@ void compute_avgs_and_dirs_2_comp(
|
|||
}
|
||||
else if (component1 == 0 && component2 == 2)
|
||||
{
|
||||
texel_weight = hadd_s(blk.channel_weight.swz<0, 2>()) / 2.0f;
|
||||
average = blk.data_mean.swz<0, 2>();
|
||||
|
||||
data_vr = blk.data_r;
|
||||
|
@ -688,7 +658,6 @@ void compute_avgs_and_dirs_2_comp(
|
|||
{
|
||||
assert(component1 == 1 && component2 == 2);
|
||||
|
||||
texel_weight = hadd_s(blk.channel_weight.swz<1, 2>()) / 2.0f;
|
||||
average = blk.data_mean.swz<1, 2>();
|
||||
|
||||
data_vr = blk.data_g;
|
||||
|
@ -714,7 +683,7 @@ void compute_avgs_and_dirs_2_comp(
|
|||
average += vfloat2(data_vr[iwt], data_vg[iwt]);
|
||||
}
|
||||
|
||||
average = average * (1.0f / static_cast<float>(texel_count));
|
||||
average = average / static_cast<float>(texel_count);
|
||||
}
|
||||
|
||||
pm[partition].avg = average;
|
||||
|
@ -737,9 +706,6 @@ void compute_avgs_and_dirs_2_comp(
|
|||
sum_yp += select(zero, texel_datum, tdm1);
|
||||
}
|
||||
|
||||
sum_xp = sum_xp * texel_weight;
|
||||
sum_yp = sum_yp * texel_weight;
|
||||
|
||||
vfloat4 prod_xp = dot(sum_xp, sum_xp);
|
||||
vfloat4 prod_yp = dot(sum_yp, sum_yp);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -330,17 +330,17 @@ static void init_decimation_info_2d(
|
|||
|
||||
for (unsigned int j = 0; j < wb.weight_count_of_texel[i]; j++)
|
||||
{
|
||||
di.texel_weights_int_4t[j][i] = wb.weights_of_texel[i][j];
|
||||
di.texel_weights_float_4t[j][i] = static_cast<float>(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM);
|
||||
di.texel_weights_4t[j][i] = wb.grid_weights_of_texel[i][j];
|
||||
di.texel_weight_contribs_int_tr[j][i] = wb.weights_of_texel[i][j];
|
||||
di.texel_weight_contribs_float_tr[j][i] = static_cast<float>(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM);
|
||||
di.texel_weights_tr[j][i] = wb.grid_weights_of_texel[i][j];
|
||||
}
|
||||
|
||||
// Init all 4 entries so we can rely on zeros for vectorization
|
||||
for (unsigned int j = wb.weight_count_of_texel[i]; j < 4; j++)
|
||||
{
|
||||
di.texel_weights_int_4t[j][i] = 0;
|
||||
di.texel_weights_float_4t[j][i] = 0.0f;
|
||||
di.texel_weights_4t[j][i] = 0;
|
||||
di.texel_weight_contribs_int_tr[j][i] = 0;
|
||||
di.texel_weight_contribs_float_tr[j][i] = 0.0f;
|
||||
di.texel_weights_tr[j][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,43 +356,30 @@ static void init_decimation_info_2d(
|
|||
uint8_t texel = wb.texels_of_weight[i][j];
|
||||
|
||||
// Create transposed versions of these for better vectorization
|
||||
di.weight_texel[j][i] = texel;
|
||||
di.weights_flt[j][i] = static_cast<float>(wb.texel_weights_of_weight[i][j]);
|
||||
di.weight_texels_tr[j][i] = texel;
|
||||
di.weights_texel_contribs_tr[j][i] = static_cast<float>(wb.texel_weights_of_weight[i][j]);
|
||||
|
||||
// perform a layer of array unrolling. An aspect of this unrolling is that
|
||||
// one of the texel-weight indexes is an identity-mapped index; we will use this
|
||||
// fact to reorder the indexes so that the first one is the identity index.
|
||||
int swap_idx = -1;
|
||||
// Store the per-texel contribution of this weight for each texel it contributes to
|
||||
di.texel_contrib_for_weight[j][i] = 0.0f;
|
||||
for (unsigned int k = 0; k < 4; k++)
|
||||
{
|
||||
uint8_t dttw = di.texel_weights_4t[k][texel];
|
||||
float dttwf = di.texel_weights_float_4t[k][texel];
|
||||
uint8_t dttw = di.texel_weights_tr[k][texel];
|
||||
float dttwf = di.texel_weight_contribs_float_tr[k][texel];
|
||||
if (dttw == i && dttwf != 0.0f)
|
||||
{
|
||||
swap_idx = k;
|
||||
di.texel_contrib_for_weight[j][i] = di.texel_weight_contribs_float_tr[k][texel];
|
||||
break;
|
||||
}
|
||||
di.texel_weights_texel[i][j][k] = dttw;
|
||||
di.texel_weights_float_texel[i][j][k] = dttwf;
|
||||
}
|
||||
|
||||
if (swap_idx != 0)
|
||||
{
|
||||
uint8_t vi = di.texel_weights_texel[i][j][0];
|
||||
float vf = di.texel_weights_float_texel[i][j][0];
|
||||
di.texel_weights_texel[i][j][0] = di.texel_weights_texel[i][j][swap_idx];
|
||||
di.texel_weights_float_texel[i][j][0] = di.texel_weights_float_texel[i][j][swap_idx];
|
||||
di.texel_weights_texel[i][j][swap_idx] = vi;
|
||||
di.texel_weights_float_texel[i][j][swap_idx] = vf;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize array tail so we can over-fetch with SIMD later to avoid loop tails
|
||||
// Match last texel in active lane in SIMD group, for better gathers
|
||||
uint8_t last_texel = di.weight_texel[texel_count_wt - 1][i];
|
||||
uint8_t last_texel = di.weight_texels_tr[texel_count_wt - 1][i];
|
||||
for (unsigned int j = texel_count_wt; j < max_texel_count_of_weight; j++)
|
||||
{
|
||||
di.weight_texel[j][i] = last_texel;
|
||||
di.weights_flt[j][i] = 0.0f;
|
||||
di.weight_texels_tr[j][i] = last_texel;
|
||||
di.weights_texel_contribs_tr[j][i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,16 +391,16 @@ static void init_decimation_info_2d(
|
|||
|
||||
for (unsigned int j = 0; j < 4; j++)
|
||||
{
|
||||
di.texel_weights_float_4t[j][i] = 0;
|
||||
di.texel_weights_4t[j][i] = 0;
|
||||
di.texel_weights_int_4t[j][i] = 0;
|
||||
di.texel_weight_contribs_float_tr[j][i] = 0;
|
||||
di.texel_weights_tr[j][i] = 0;
|
||||
di.texel_weight_contribs_int_tr[j][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize array tail so we can over-fetch with SIMD later to avoid loop tails
|
||||
// Match last texel in active lane in SIMD group, for better gathers
|
||||
unsigned int last_texel_count_wt = wb.texel_count_of_weight[weights_per_block - 1];
|
||||
uint8_t last_texel = di.weight_texel[last_texel_count_wt - 1][weights_per_block - 1];
|
||||
uint8_t last_texel = di.weight_texels_tr[last_texel_count_wt - 1][weights_per_block - 1];
|
||||
|
||||
unsigned int weights_per_block_simd = round_up_to_simd_multiple_vla(weights_per_block);
|
||||
for (unsigned int i = weights_per_block; i < weights_per_block_simd; i++)
|
||||
|
@ -422,8 +409,8 @@ static void init_decimation_info_2d(
|
|||
|
||||
for (unsigned int j = 0; j < max_texel_count_of_weight; j++)
|
||||
{
|
||||
di.weight_texel[j][i] = last_texel;
|
||||
di.weights_flt[j][i] = 0.0f;
|
||||
di.weight_texels_tr[j][i] = last_texel;
|
||||
di.weights_texel_contribs_tr[j][i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,16 +587,16 @@ static void init_decimation_info_3d(
|
|||
// Init all 4 entries so we can rely on zeros for vectorization
|
||||
for (unsigned int j = 0; j < 4; j++)
|
||||
{
|
||||
di.texel_weights_int_4t[j][i] = 0;
|
||||
di.texel_weights_float_4t[j][i] = 0.0f;
|
||||
di.texel_weights_4t[j][i] = 0;
|
||||
di.texel_weight_contribs_int_tr[j][i] = 0;
|
||||
di.texel_weight_contribs_float_tr[j][i] = 0.0f;
|
||||
di.texel_weights_tr[j][i] = 0;
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < wb.weight_count_of_texel[i]; j++)
|
||||
{
|
||||
di.texel_weights_int_4t[j][i] = wb.weights_of_texel[i][j];
|
||||
di.texel_weights_float_4t[j][i] = static_cast<float>(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM);
|
||||
di.texel_weights_4t[j][i] = wb.grid_weights_of_texel[i][j];
|
||||
di.texel_weight_contribs_int_tr[j][i] = wb.weights_of_texel[i][j];
|
||||
di.texel_weight_contribs_float_tr[j][i] = static_cast<float>(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM);
|
||||
di.texel_weights_tr[j][i] = wb.grid_weights_of_texel[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,43 +612,30 @@ static void init_decimation_info_3d(
|
|||
unsigned int texel = wb.texels_of_weight[i][j];
|
||||
|
||||
// Create transposed versions of these for better vectorization
|
||||
di.weight_texel[j][i] = static_cast<uint8_t>(texel);
|
||||
di.weights_flt[j][i] = static_cast<float>(wb.texel_weights_of_weight[i][j]);
|
||||
di.weight_texels_tr[j][i] = static_cast<uint8_t>(texel);
|
||||
di.weights_texel_contribs_tr[j][i] = static_cast<float>(wb.texel_weights_of_weight[i][j]);
|
||||
|
||||
// perform a layer of array unrolling. An aspect of this unrolling is that
|
||||
// one of the texel-weight indexes is an identity-mapped index; we will use this
|
||||
// fact to reorder the indexes so that the first one is the identity index.
|
||||
int swap_idx = -1;
|
||||
// Store the per-texel contribution of this weight for each texel it contributes to
|
||||
di.texel_contrib_for_weight[j][i] = 0.0f;
|
||||
for (unsigned int k = 0; k < 4; k++)
|
||||
{
|
||||
uint8_t dttw = di.texel_weights_4t[k][texel];
|
||||
float dttwf = di.texel_weights_float_4t[k][texel];
|
||||
uint8_t dttw = di.texel_weights_tr[k][texel];
|
||||
float dttwf = di.texel_weight_contribs_float_tr[k][texel];
|
||||
if (dttw == i && dttwf != 0.0f)
|
||||
{
|
||||
swap_idx = k;
|
||||
di.texel_contrib_for_weight[j][i] = di.texel_weight_contribs_float_tr[k][texel];
|
||||
break;
|
||||
}
|
||||
di.texel_weights_texel[i][j][k] = dttw;
|
||||
di.texel_weights_float_texel[i][j][k] = dttwf;
|
||||
}
|
||||
|
||||
if (swap_idx != 0)
|
||||
{
|
||||
uint8_t vi = di.texel_weights_texel[i][j][0];
|
||||
float vf = di.texel_weights_float_texel[i][j][0];
|
||||
di.texel_weights_texel[i][j][0] = di.texel_weights_texel[i][j][swap_idx];
|
||||
di.texel_weights_float_texel[i][j][0] = di.texel_weights_float_texel[i][j][swap_idx];
|
||||
di.texel_weights_texel[i][j][swap_idx] = vi;
|
||||
di.texel_weights_float_texel[i][j][swap_idx] = vf;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize array tail so we can over-fetch with SIMD later to avoid loop tails
|
||||
// Match last texel in active lane in SIMD group, for better gathers
|
||||
uint8_t last_texel = di.weight_texel[texel_count_wt - 1][i];
|
||||
uint8_t last_texel = di.weight_texels_tr[texel_count_wt - 1][i];
|
||||
for (unsigned int j = texel_count_wt; j < max_texel_count_of_weight; j++)
|
||||
{
|
||||
di.weight_texel[j][i] = last_texel;
|
||||
di.weights_flt[j][i] = 0.0f;
|
||||
di.weight_texels_tr[j][i] = last_texel;
|
||||
di.weights_texel_contribs_tr[j][i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,16 +647,16 @@ static void init_decimation_info_3d(
|
|||
|
||||
for (unsigned int j = 0; j < 4; j++)
|
||||
{
|
||||
di.texel_weights_float_4t[j][i] = 0;
|
||||
di.texel_weights_4t[j][i] = 0;
|
||||
di.texel_weights_int_4t[j][i] = 0;
|
||||
di.texel_weight_contribs_float_tr[j][i] = 0;
|
||||
di.texel_weights_tr[j][i] = 0;
|
||||
di.texel_weight_contribs_int_tr[j][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize array tail so we can over-fetch with SIMD later to avoid loop tails
|
||||
// Match last texel in active lane in SIMD group, for better gathers
|
||||
int last_texel_count_wt = wb.texel_count_of_weight[weights_per_block - 1];
|
||||
uint8_t last_texel = di.weight_texel[last_texel_count_wt - 1][weights_per_block - 1];
|
||||
uint8_t last_texel = di.weight_texels_tr[last_texel_count_wt - 1][weights_per_block - 1];
|
||||
|
||||
unsigned int weights_per_block_simd = round_up_to_simd_multiple_vla(weights_per_block);
|
||||
for (unsigned int i = weights_per_block; i < weights_per_block_simd; i++)
|
||||
|
@ -691,8 +665,8 @@ static void init_decimation_info_3d(
|
|||
|
||||
for (int j = 0; j < max_texel_count_of_weight; j++)
|
||||
{
|
||||
di.weight_texel[j][i] = last_texel;
|
||||
di.weights_flt[j][i] = 0.0f;
|
||||
di.weight_texels_tr[j][i] = last_texel;
|
||||
di.weights_texel_contribs_tr[j][i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1006,7 +980,7 @@ static void construct_block_size_descriptor_2d(
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate block modes and decimation tables for a single £D block size.
|
||||
* @brief Allocate block modes and decimation tables for a single 3D block size.
|
||||
*
|
||||
* TODO: This function doesn't include all of the heuristics that we use for 2D block sizes such as
|
||||
* the percentile mode cutoffs. If 3D becomes more widely used we should look at this.
|
||||
|
|
|
@ -40,24 +40,6 @@
|
|||
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/**
|
||||
* @brief Determine the quantized value given a quantization level.
|
||||
*
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param value The value to convert. This may be outside of the 0-255 range and will be
|
||||
* clamped before the value is looked up.
|
||||
*
|
||||
* @return The encoded quantized value. These are not necessarily in order; the compressor
|
||||
* scrambles the values slightly to make hardware implementation easier.
|
||||
*/
|
||||
static inline int quant_color_clamp(
|
||||
quant_method quant_level,
|
||||
int value
|
||||
) {
|
||||
value = astc::clamp(value, 0, 255);
|
||||
return color_quant_tables[quant_level - QUANT_6][value];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine the quantized value given a quantization level.
|
||||
*
|
||||
|
@ -72,23 +54,7 @@ static inline uint8_t quant_color(
|
|||
quant_method quant_level,
|
||||
int value
|
||||
) {
|
||||
return color_quant_tables[quant_level - QUANT_6][value];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine the unquantized value given a quantization level.
|
||||
*
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param value The value to convert.
|
||||
*
|
||||
* @return The encoded quantized value. These are not necessarily in order; the compressor
|
||||
* scrambles the values slightly to make hardware implementation easier.
|
||||
*/
|
||||
static inline uint8_t unquant_color(
|
||||
quant_method quant_level,
|
||||
int value
|
||||
) {
|
||||
return color_unquant_tables[quant_level - QUANT_6][value];
|
||||
return color_unquant_to_uquant_tables[quant_level - QUANT_6][value];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,28 +86,20 @@ static void quantize_rgb(
|
|||
float b1 = astc::clamp255f(color1.lane<2>() * scale);
|
||||
|
||||
int ri0, gi0, bi0, ri1, gi1, bi1;
|
||||
int ri0b, gi0b, bi0b, ri1b, gi1b, bi1b;
|
||||
float rgb0_addon = 0.5f;
|
||||
float rgb1_addon = 0.5f;
|
||||
do
|
||||
{
|
||||
ri0 = quant_color_clamp(quant_level, astc::flt2int_rd(r0 + rgb0_addon));
|
||||
gi0 = quant_color_clamp(quant_level, astc::flt2int_rd(g0 + rgb0_addon));
|
||||
bi0 = quant_color_clamp(quant_level, astc::flt2int_rd(b0 + rgb0_addon));
|
||||
ri1 = quant_color_clamp(quant_level, astc::flt2int_rd(r1 + rgb1_addon));
|
||||
gi1 = quant_color_clamp(quant_level, astc::flt2int_rd(g1 + rgb1_addon));
|
||||
bi1 = quant_color_clamp(quant_level, astc::flt2int_rd(b1 + rgb1_addon));
|
||||
|
||||
ri0b = unquant_color(quant_level, ri0);
|
||||
gi0b = unquant_color(quant_level, gi0);
|
||||
bi0b = unquant_color(quant_level, bi0);
|
||||
ri1b = unquant_color(quant_level, ri1);
|
||||
gi1b = unquant_color(quant_level, gi1);
|
||||
bi1b = unquant_color(quant_level, bi1);
|
||||
ri0 = quant_color(quant_level, astc::max(astc::flt2int_rd(r0 + rgb0_addon), 0));
|
||||
gi0 = quant_color(quant_level, astc::max(astc::flt2int_rd(g0 + rgb0_addon), 0));
|
||||
bi0 = quant_color(quant_level, astc::max(astc::flt2int_rd(b0 + rgb0_addon), 0));
|
||||
ri1 = quant_color(quant_level, astc::min(astc::flt2int_rd(r1 + rgb1_addon), 255));
|
||||
gi1 = quant_color(quant_level, astc::min(astc::flt2int_rd(g1 + rgb1_addon), 255));
|
||||
bi1 = quant_color(quant_level, astc::min(astc::flt2int_rd(b1 + rgb1_addon), 255));
|
||||
|
||||
rgb0_addon -= 0.2f;
|
||||
rgb1_addon += 0.2f;
|
||||
} while (ri0b + gi0b + bi0b > ri1b + gi1b + bi1b);
|
||||
} while (ri0 + gi0 + bi0 > ri1 + gi1 + bi1);
|
||||
|
||||
output[0] = static_cast<uint8_t>(ri0);
|
||||
output[1] = static_cast<uint8_t>(ri1);
|
||||
|
@ -230,18 +188,9 @@ static bool try_quantize_rgb_blue_contract(
|
|||
int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1));
|
||||
int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1));
|
||||
|
||||
// Then unquantize again
|
||||
int ru0 = unquant_color(quant_level, ri0);
|
||||
int gu0 = unquant_color(quant_level, gi0);
|
||||
int bu0 = unquant_color(quant_level, bi0);
|
||||
|
||||
int ru1 = unquant_color(quant_level, ri1);
|
||||
int gu1 = unquant_color(quant_level, gi1);
|
||||
int bu1 = unquant_color(quant_level, bi1);
|
||||
|
||||
// If color #1 is not larger than color #0 then blue-contraction cannot be used. Note that
|
||||
// blue-contraction and quantization change this order, which is why we must test aftwards.
|
||||
if (ru1 + gu1 + bu1 <= ru0 + gu0 + bu0)
|
||||
// blue-contraction and quantization change this order, which is why we must test afterwards.
|
||||
if (ri1 + gi1 + bi1 <= ri0 + gi0 + bi0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -334,13 +283,9 @@ static bool try_quantize_rgb_delta(
|
|||
int g0be = quant_color(quant_level, g0b);
|
||||
int b0be = quant_color(quant_level, b0b);
|
||||
|
||||
r0b = unquant_color(quant_level, r0be);
|
||||
g0b = unquant_color(quant_level, g0be);
|
||||
b0b = unquant_color(quant_level, b0be);
|
||||
|
||||
r0b |= r0a & 0x100;
|
||||
g0b |= g0a & 0x100;
|
||||
b0b |= b0a & 0x100;
|
||||
r0b = r0be | (r0a & 0x100);
|
||||
g0b = g0be | (g0a & 0x100);
|
||||
b0b = b0be | (b0a & 0x100);
|
||||
|
||||
// Get hold of the second value
|
||||
int r1d = astc::flt2int_rtn(r1);
|
||||
|
@ -377,45 +322,23 @@ static bool try_quantize_rgb_delta(
|
|||
int g1de = quant_color(quant_level, g1d);
|
||||
int b1de = quant_color(quant_level, b1d);
|
||||
|
||||
int r1du = unquant_color(quant_level, r1de);
|
||||
int g1du = unquant_color(quant_level, g1de);
|
||||
int b1du = unquant_color(quant_level, b1de);
|
||||
|
||||
if (((r1d ^ r1du) | (g1d ^ g1du) | (b1d ^ b1du)) & 0xC0)
|
||||
if (((r1d ^ r1de) | (g1d ^ g1de) | (b1d ^ b1de)) & 0xC0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the sum of the encoded offsets is nonnegative, else encoding fails
|
||||
r1du &= 0x7f;
|
||||
g1du &= 0x7f;
|
||||
b1du &= 0x7f;
|
||||
|
||||
if (r1du & 0x40)
|
||||
{
|
||||
r1du -= 0x80;
|
||||
}
|
||||
|
||||
if (g1du & 0x40)
|
||||
{
|
||||
g1du -= 0x80;
|
||||
}
|
||||
|
||||
if (b1du & 0x40)
|
||||
{
|
||||
b1du -= 0x80;
|
||||
}
|
||||
|
||||
if (r1du + g1du + b1du < 0)
|
||||
// If the sum of offsets triggers blue-contraction then encoding fails
|
||||
vint4 ep0(r0be, g0be, b0be, 0);
|
||||
vint4 ep1(r1de, g1de, b1de, 0);
|
||||
bit_transfer_signed(ep1, ep0);
|
||||
if (hadd_rgb_s(ep1) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the offsets produce legitimate sums as well
|
||||
r1du += r0b;
|
||||
g1du += g0b;
|
||||
b1du += b0b;
|
||||
if (r1du < 0 || r1du > 0x1FF || g1du < 0 || g1du > 0x1FF || b1du < 0 || b1du > 0x1FF)
|
||||
ep0 = ep0 + ep1;
|
||||
if (any((ep0 < vint4(0)) | (ep0 > vint4(0xFF))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -477,13 +400,9 @@ static bool try_quantize_rgb_delta_blue_contract(
|
|||
int g0be = quant_color(quant_level, g0b);
|
||||
int b0be = quant_color(quant_level, b0b);
|
||||
|
||||
r0b = unquant_color(quant_level, r0be);
|
||||
g0b = unquant_color(quant_level, g0be);
|
||||
b0b = unquant_color(quant_level, b0be);
|
||||
|
||||
r0b |= r0a & 0x100;
|
||||
g0b |= g0a & 0x100;
|
||||
b0b |= b0a & 0x100;
|
||||
r0b = r0be | (r0a & 0x100);
|
||||
g0b = g0be | (g0a & 0x100);
|
||||
b0b = b0be | (b0a & 0x100);
|
||||
|
||||
// Get hold of the second value
|
||||
int r1d = astc::flt2int_rtn(r1);
|
||||
|
@ -521,47 +440,23 @@ static bool try_quantize_rgb_delta_blue_contract(
|
|||
int g1de = quant_color(quant_level, g1d);
|
||||
int b1de = quant_color(quant_level, b1d);
|
||||
|
||||
int r1du = unquant_color(quant_level, r1de);
|
||||
int g1du = unquant_color(quant_level, g1de);
|
||||
int b1du = unquant_color(quant_level, b1de);
|
||||
|
||||
if (((r1d ^ r1du) | (g1d ^ g1du) | (b1d ^ b1du)) & 0xC0)
|
||||
if (((r1d ^ r1de) | (g1d ^ g1de) | (b1d ^ b1de)) & 0xC0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the sum of the encoded offsets is negative, else encoding fails
|
||||
// Note that this is inverse of the test for non-blue-contracted RGB.
|
||||
r1du &= 0x7f;
|
||||
g1du &= 0x7f;
|
||||
b1du &= 0x7f;
|
||||
|
||||
if (r1du & 0x40)
|
||||
{
|
||||
r1du -= 0x80;
|
||||
}
|
||||
|
||||
if (g1du & 0x40)
|
||||
{
|
||||
g1du -= 0x80;
|
||||
}
|
||||
|
||||
if (b1du & 0x40)
|
||||
{
|
||||
b1du -= 0x80;
|
||||
}
|
||||
|
||||
if (r1du + g1du + b1du >= 0)
|
||||
// If the sum of offsets does not trigger blue-contraction then encoding fails
|
||||
vint4 ep0(r0be, g0be, b0be, 0);
|
||||
vint4 ep1(r1de, g1de, b1de, 0);
|
||||
bit_transfer_signed(ep1, ep0);
|
||||
if (hadd_rgb_s(ep1) >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the offsets produce legitimate sums as well
|
||||
r1du += r0b;
|
||||
g1du += g0b;
|
||||
b1du += b0b;
|
||||
|
||||
if (r1du < 0 || r1du > 0x1FF || g1du < 0 || g1du > 0x1FF || b1du < 0 || b1du > 0x1FF)
|
||||
ep0 = ep0 + ep1;
|
||||
if (any((ep0 < vint4(0)) | (ep0 > vint4(0xFF))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -607,7 +502,7 @@ static bool try_quantize_alpha_delta(
|
|||
a0a <<= 1;
|
||||
int a0b = a0a & 0xFF;
|
||||
int a0be = quant_color(quant_level, a0b);
|
||||
a0b = unquant_color(quant_level, a0be);
|
||||
a0b = a0be;
|
||||
a0b |= a0a & 0x100;
|
||||
int a1d = astc::flt2int_rtn(a1);
|
||||
a1d <<= 1;
|
||||
|
@ -622,7 +517,7 @@ static bool try_quantize_alpha_delta(
|
|||
a1d |= (a0b & 0x100) >> 1;
|
||||
|
||||
int a1de = quant_color(quant_level, a1d);
|
||||
int a1du = unquant_color(quant_level, a1de);
|
||||
int a1du = a1de;
|
||||
if ((a1d ^ a1du) & 0xC0)
|
||||
{
|
||||
return false;
|
||||
|
@ -685,8 +580,8 @@ static bool try_quantize_luminance_alpha_delta(
|
|||
int a0b = a0a & 0xFF;
|
||||
int l0be = quant_color(quant_level, l0b);
|
||||
int a0be = quant_color(quant_level, a0b);
|
||||
l0b = unquant_color(quant_level, l0be);
|
||||
a0b = unquant_color(quant_level, a0be);
|
||||
l0b = l0be;
|
||||
a0b = a0be;
|
||||
l0b |= l0a & 0x100;
|
||||
a0b |= a0a & 0x100;
|
||||
|
||||
|
@ -714,8 +609,8 @@ static bool try_quantize_luminance_alpha_delta(
|
|||
|
||||
int l1de = quant_color(quant_level, l1d);
|
||||
int a1de = quant_color(quant_level, a1d);
|
||||
int l1du = unquant_color(quant_level, l1de);
|
||||
int a1du = unquant_color(quant_level, a1de);
|
||||
int l1du = l1de;
|
||||
int a1du = a1de;
|
||||
|
||||
if ((l1d ^ l1du) & 0xC0)
|
||||
{
|
||||
|
@ -837,12 +732,8 @@ static void quantize_rgbs(
|
|||
int gi = quant_color(quant_level, astc::flt2int_rtn(g));
|
||||
int bi = quant_color(quant_level, astc::flt2int_rtn(b));
|
||||
|
||||
int ru = unquant_color(quant_level, ri);
|
||||
int gu = unquant_color(quant_level, gi);
|
||||
int bu = unquant_color(quant_level, bi);
|
||||
|
||||
float oldcolorsum = hadd_rgb_s(color) * scale;
|
||||
float newcolorsum = static_cast<float>(ru + gu + bu);
|
||||
float newcolorsum = static_cast<float>(ri + gi + bi);
|
||||
|
||||
float scalea = astc::clamp1f(color.lane<3>() * (oldcolorsum + 1e-10f) / (newcolorsum + 1e-10f));
|
||||
int scale_idx = astc::flt2int_rtn(scalea * 256.0f);
|
||||
|
@ -987,33 +878,29 @@ static void quantize_luminance_alpha(
|
|||
* @param quant_level The quantization level to use.
|
||||
* @param value The input unquantized value.
|
||||
* @param[out] quant_value The quantized value.
|
||||
* @param[out] unquant_value The unquantized value after quantization.
|
||||
*/
|
||||
static inline void quantize_and_unquantize_retain_top_two_bits(
|
||||
quant_method quant_level,
|
||||
uint8_t value,
|
||||
uint8_t& quant_value,
|
||||
uint8_t& unquant_value
|
||||
uint8_t& quant_value
|
||||
) {
|
||||
int perform_loop;
|
||||
uint8_t quantval;
|
||||
uint8_t uquantval;
|
||||
|
||||
do
|
||||
{
|
||||
quantval = quant_color(quant_level, value);
|
||||
uquantval = unquant_color(quant_level, quantval);
|
||||
|
||||
// Perform looping if the top two bits were modified by quant/unquant
|
||||
perform_loop = (value & 0xC0) != (uquantval & 0xC0);
|
||||
perform_loop = (value & 0xC0) != (quantval & 0xC0);
|
||||
|
||||
if ((uquantval & 0xC0) > (value & 0xC0))
|
||||
if ((quantval & 0xC0) > (value & 0xC0))
|
||||
{
|
||||
// Quant/unquant rounded UP so that the top two bits changed;
|
||||
// decrement the input in hopes that this will avoid rounding up.
|
||||
value--;
|
||||
}
|
||||
else if ((uquantval & 0xC0) < (value & 0xC0))
|
||||
else if ((quantval & 0xC0) < (value & 0xC0))
|
||||
{
|
||||
// Quant/unquant rounded DOWN so that the top two bits changed;
|
||||
// decrement the input in hopes that this will avoid rounding down.
|
||||
|
@ -1022,7 +909,6 @@ static inline void quantize_and_unquantize_retain_top_two_bits(
|
|||
} while (perform_loop);
|
||||
|
||||
quant_value = quantval;
|
||||
unquant_value = uquantval;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1030,34 +916,29 @@ static inline void quantize_and_unquantize_retain_top_two_bits(
|
|||
*
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param value The input unquantized value.
|
||||
* @param[out] quant_value The quantized value.
|
||||
* @param[out] unquant_value The unquantized value after quantization.
|
||||
* @param[out] quant_value The quantized value in 0-255 range.
|
||||
*/
|
||||
static inline void quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_method quant_level,
|
||||
uint8_t value,
|
||||
uint8_t& quant_value,
|
||||
uint8_t& unquant_value
|
||||
uint8_t& quant_value
|
||||
) {
|
||||
uint8_t perform_loop;
|
||||
uint8_t quantval;
|
||||
uint8_t uquantval;
|
||||
|
||||
do
|
||||
{
|
||||
quantval = quant_color(quant_level, value);
|
||||
uquantval = unquant_color(quant_level, quantval);
|
||||
|
||||
// Perform looping if the top four bits were modified by quant/unquant
|
||||
perform_loop = (value & 0xF0) != (uquantval & 0xF0);
|
||||
perform_loop = (value & 0xF0) != (quantval & 0xF0);
|
||||
|
||||
if ((uquantval & 0xF0) > (value & 0xF0))
|
||||
if ((quantval & 0xF0) > (value & 0xF0))
|
||||
{
|
||||
// Quant/unquant rounded UP so that the top four bits changed;
|
||||
// decrement the input value in hopes that this will avoid rounding up.
|
||||
value--;
|
||||
}
|
||||
else if ((uquantval & 0xF0) < (value & 0xF0))
|
||||
else if ((quantval & 0xF0) < (value & 0xF0))
|
||||
{
|
||||
// Quant/unquant rounded DOWN so that the top four bits changed;
|
||||
// decrement the input value in hopes that this will avoid rounding down.
|
||||
|
@ -1066,7 +947,6 @@ static inline void quantize_and_unquantize_retain_top_four_bits(
|
|||
} while (perform_loop);
|
||||
|
||||
quant_value = quantval;
|
||||
unquant_value = uquantval;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1177,11 +1057,10 @@ static void quantize_hdr_rgbo(
|
|||
r_lowbits |= (mode_enc & 3) << 6;
|
||||
|
||||
uint8_t r_quantval;
|
||||
uint8_t r_uquantval;
|
||||
quantize_and_unquantize_retain_top_two_bits(
|
||||
quant_level, static_cast<uint8_t>(r_lowbits), r_quantval, r_uquantval);
|
||||
quant_level, static_cast<uint8_t>(r_lowbits), r_quantval);
|
||||
|
||||
r_intval = (r_intval & ~0x3f) | (r_uquantval & 0x3f);
|
||||
r_intval = (r_intval & ~0x3f) | (r_quantval & 0x3f);
|
||||
float r_fval = static_cast<float>(r_intval) * mode_rscale;
|
||||
|
||||
// Recompute G and B, then quantize and unquantize them
|
||||
|
@ -1277,16 +1156,14 @@ static void quantize_hdr_rgbo(
|
|||
|
||||
uint8_t g_quantval;
|
||||
uint8_t b_quantval;
|
||||
uint8_t g_uquantval;
|
||||
uint8_t b_uquantval;
|
||||
|
||||
quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_level, static_cast<uint8_t>(g_lowbits), g_quantval, g_uquantval);
|
||||
quant_level, static_cast<uint8_t>(g_lowbits), g_quantval);
|
||||
quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_level, static_cast<uint8_t>(b_lowbits), b_quantval, b_uquantval);
|
||||
quant_level, static_cast<uint8_t>(b_lowbits), b_quantval);
|
||||
|
||||
g_intval = (g_intval & ~0x1f) | (g_uquantval & 0x1f);
|
||||
b_intval = (b_intval & ~0x1f) | (b_uquantval & 0x1f);
|
||||
g_intval = (g_intval & ~0x1f) | (g_quantval & 0x1f);
|
||||
b_intval = (b_intval & ~0x1f) | (b_quantval & 0x1f);
|
||||
|
||||
g_fval = static_cast<float>(g_intval) * mode_rscale;
|
||||
b_fval = static_cast<float>(b_intval) * mode_rscale;
|
||||
|
@ -1350,10 +1227,9 @@ static void quantize_hdr_rgbo(
|
|||
s_lowbits |= bit4 << 7;
|
||||
|
||||
uint8_t s_quantval;
|
||||
uint8_t s_uquantval;
|
||||
|
||||
quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_level, static_cast<uint8_t>(s_lowbits), s_quantval, s_uquantval);
|
||||
quant_level, static_cast<uint8_t>(s_lowbits), s_quantval);
|
||||
|
||||
output[0] = r_quantval;
|
||||
output[1] = g_quantval;
|
||||
|
@ -1393,9 +1269,8 @@ static void quantize_hdr_rgbo(
|
|||
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
uint8_t dummy;
|
||||
quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_level, static_cast<uint8_t>(encvals[i]), output[i], dummy);
|
||||
quant_level, static_cast<uint8_t>(encvals[i]), output[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1535,7 +1410,7 @@ static void quantize_hdr_rgb(
|
|||
int a_lowbits = a_intval & 0xFF;
|
||||
|
||||
int a_quantval = quant_color(quant_level, a_lowbits);
|
||||
int a_uquantval = unquant_color(quant_level, a_quantval);
|
||||
int a_uquantval = a_quantval;
|
||||
a_intval = (a_intval & ~0xFF) | a_uquantval;
|
||||
float a_fval = static_cast<float>(a_intval) * mode_rscale;
|
||||
|
||||
|
@ -1556,12 +1431,11 @@ static void quantize_hdr_rgb(
|
|||
c_lowbits |= (a_intval & 0x100) >> 2;
|
||||
|
||||
uint8_t c_quantval;
|
||||
uint8_t c_uquantval;
|
||||
|
||||
quantize_and_unquantize_retain_top_two_bits(
|
||||
quant_level, static_cast<uint8_t>(c_lowbits), c_quantval, c_uquantval);
|
||||
quant_level, static_cast<uint8_t>(c_lowbits), c_quantval);
|
||||
|
||||
c_intval = (c_intval & ~0x3F) | (c_uquantval & 0x3F);
|
||||
c_intval = (c_intval & ~0x3F) | (c_quantval & 0x3F);
|
||||
c_fval = static_cast<float>(c_intval) * mode_rscale;
|
||||
|
||||
// Recompute B0 and B1, then quantize and unquantize them
|
||||
|
@ -1625,16 +1499,14 @@ static void quantize_hdr_rgb(
|
|||
|
||||
uint8_t b0_quantval;
|
||||
uint8_t b1_quantval;
|
||||
uint8_t b0_uquantval;
|
||||
uint8_t b1_uquantval;
|
||||
|
||||
quantize_and_unquantize_retain_top_two_bits(
|
||||
quant_level, static_cast<uint8_t>(b0_lowbits), b0_quantval, b0_uquantval);
|
||||
quant_level, static_cast<uint8_t>(b0_lowbits), b0_quantval);
|
||||
quantize_and_unquantize_retain_top_two_bits(
|
||||
quant_level, static_cast<uint8_t>(b1_lowbits), b1_quantval, b1_uquantval);
|
||||
quant_level, static_cast<uint8_t>(b1_lowbits), b1_quantval);
|
||||
|
||||
b0_intval = (b0_intval & ~0x3f) | (b0_uquantval & 0x3f);
|
||||
b1_intval = (b1_intval & ~0x3f) | (b1_uquantval & 0x3f);
|
||||
b0_intval = (b0_intval & ~0x3f) | (b0_quantval & 0x3f);
|
||||
b1_intval = (b1_intval & ~0x3f) | (b1_quantval & 0x3f);
|
||||
b0_fval = static_cast<float>(b0_intval) * mode_rscale;
|
||||
b1_fval = static_cast<float>(b1_intval) * mode_rscale;
|
||||
|
||||
|
@ -1722,13 +1594,11 @@ static void quantize_hdr_rgb(
|
|||
|
||||
uint8_t d0_quantval;
|
||||
uint8_t d1_quantval;
|
||||
uint8_t d0_uquantval;
|
||||
uint8_t d1_uquantval;
|
||||
|
||||
quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_level, static_cast<uint8_t>(d0_lowbits), d0_quantval, d0_uquantval);
|
||||
quant_level, static_cast<uint8_t>(d0_lowbits), d0_quantval);
|
||||
quantize_and_unquantize_retain_top_four_bits(
|
||||
quant_level, static_cast<uint8_t>(d1_lowbits), d1_quantval, d1_uquantval);
|
||||
quant_level, static_cast<uint8_t>(d1_lowbits), d1_quantval);
|
||||
|
||||
output[0] = static_cast<uint8_t>(a_quantval);
|
||||
output[1] = c_quantval;
|
||||
|
@ -1764,10 +1634,9 @@ static void quantize_hdr_rgb(
|
|||
|
||||
for (int i = 4; i < 6; i++)
|
||||
{
|
||||
uint8_t dummy;
|
||||
int idx = astc::flt2int_rtn(vals[i] * 1.0f / 512.0f) + 128;
|
||||
quantize_and_unquantize_retain_top_two_bits(
|
||||
quant_level, static_cast<uint8_t>(idx), output[i], dummy);
|
||||
quant_level, static_cast<uint8_t>(idx), output[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1919,7 +1788,7 @@ static bool try_quantize_hdr_luminance_small_range(
|
|||
|
||||
v0 = lowval & 0x7F;
|
||||
v0e = quant_color(quant_level, v0);
|
||||
v0d = unquant_color(quant_level, v0e);
|
||||
v0d = v0e;
|
||||
|
||||
if (v0d < 0x80)
|
||||
{
|
||||
|
@ -1929,7 +1798,7 @@ static bool try_quantize_hdr_luminance_small_range(
|
|||
{
|
||||
v1 = ((lowval >> 3) & 0xF0) | diffval;
|
||||
v1e = quant_color(quant_level, v1);
|
||||
v1d = unquant_color(quant_level, v1e);
|
||||
v1d = v1e;
|
||||
if ((v1d & 0xF0) == (v1 & 0xF0))
|
||||
{
|
||||
output[0] = static_cast<uint8_t>(v0e);
|
||||
|
@ -1948,7 +1817,7 @@ static bool try_quantize_hdr_luminance_small_range(
|
|||
|
||||
v0 = (lowval & 0x7F) | 0x80;
|
||||
v0e = quant_color(quant_level, v0);
|
||||
v0d = unquant_color(quant_level, v0e);
|
||||
v0d = v0e;
|
||||
if ((v0d & 0x80) == 0)
|
||||
{
|
||||
return false;
|
||||
|
@ -1963,7 +1832,7 @@ static bool try_quantize_hdr_luminance_small_range(
|
|||
|
||||
v1 = ((lowval >> 2) & 0xE0) | diffval;
|
||||
v1e = quant_color(quant_level, v1);
|
||||
v1d = unquant_color(quant_level, v1e);
|
||||
v1d = v1e;
|
||||
if ((v1d & 0xE0) != (v1 & 0xE0))
|
||||
{
|
||||
return false;
|
||||
|
@ -2007,7 +1876,7 @@ static void quantize_hdr_alpha(
|
|||
|
||||
v6 = (val0 & 0x7F) | ((i & 1) << 7);
|
||||
v6e = quant_color(quant_level, v6);
|
||||
v6d = unquant_color(quant_level, v6e);
|
||||
v6d = v6e;
|
||||
|
||||
if ((v6 ^ v6d) & 0x80)
|
||||
{
|
||||
|
@ -2026,7 +1895,7 @@ static void quantize_hdr_alpha(
|
|||
|
||||
v7 = ((i & 2) << 6) | ((val0 >> 7) << (6 - i)) | (diffval & mask);
|
||||
v7e = quant_color(quant_level, v7);
|
||||
v7d = unquant_color(quant_level, v7e);
|
||||
v7d = v7e;
|
||||
|
||||
static const int testbits[3] { 0xE0, 0xF0, 0xF8 };
|
||||
|
||||
|
@ -2091,7 +1960,7 @@ uint8_t pack_color_endpoints(
|
|||
switch (format)
|
||||
{
|
||||
case FMT_RGB:
|
||||
if (quant_level <= 18)
|
||||
if (quant_level <= QUANT_160)
|
||||
{
|
||||
if (try_quantize_rgb_delta_blue_contract(color0, color1, output, quant_level))
|
||||
{
|
||||
|
@ -2104,7 +1973,7 @@ uint8_t pack_color_endpoints(
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (try_quantize_rgb_blue_contract(color0, color1, output, quant_level))
|
||||
if (quant_level < QUANT_256 && try_quantize_rgb_blue_contract(color0, color1, output, quant_level))
|
||||
{
|
||||
retval = FMT_RGB;
|
||||
break;
|
||||
|
@ -2114,7 +1983,7 @@ uint8_t pack_color_endpoints(
|
|||
break;
|
||||
|
||||
case FMT_RGBA:
|
||||
if (quant_level <= 18)
|
||||
if (quant_level <= QUANT_160)
|
||||
{
|
||||
if (try_quantize_rgba_delta_blue_contract(color0, color1, output, quant_level))
|
||||
{
|
||||
|
@ -2127,7 +1996,7 @@ uint8_t pack_color_endpoints(
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (try_quantize_rgba_blue_contract(color0, color1, output, quant_level))
|
||||
if (quant_level < QUANT_256 && try_quantize_rgba_blue_contract(color0, color1, output, quant_level))
|
||||
{
|
||||
retval = FMT_RGBA;
|
||||
break;
|
||||
|
|
|
@ -23,43 +23,6 @@
|
|||
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/**
|
||||
* @brief Unquantize a color.
|
||||
*
|
||||
* This function uses a lookup table as the quantization is encoded to make
|
||||
* hardware implementations easier, and is not a simple lerp.
|
||||
*
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param inputq The input quantized color.
|
||||
*
|
||||
* @return The unquantized color.
|
||||
*/
|
||||
static ASTCENC_SIMD_INLINE vint4 unquant_color(
|
||||
quant_method quant_level,
|
||||
vint4 inputq
|
||||
) {
|
||||
const uint8_t* unq = color_unquant_tables[quant_level - QUANT_6];
|
||||
return vint4(unq[inputq.lane<0>()], unq[inputq.lane<1>()],
|
||||
unq[inputq.lane<2>()], unq[inputq.lane<3>()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine the quantized value given a quantization level.
|
||||
*
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param value The value to convert. This may be outside of the 0-255 range and will be
|
||||
* clamped before the value is looked up.
|
||||
*
|
||||
* @return The encoded quantized value. These are not necessarily in order; the compressor
|
||||
* scrambles the values slightly to make hardware implementation easier.
|
||||
*/
|
||||
static inline uint8_t unquant_color(
|
||||
quant_method quant_level,
|
||||
int value
|
||||
) {
|
||||
return color_unquant_tables[quant_level - QUANT_6][value];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Un-blue-contract a color.
|
||||
*
|
||||
|
@ -80,32 +43,19 @@ static ASTCENC_SIMD_INLINE vint4 uncontract_color(
|
|||
/**
|
||||
* @brief Unpack an LDR RGBA color that uses delta encoding.
|
||||
*
|
||||
* @param input0q The raw quantized endpoint 0 color.
|
||||
* @param input1q The raw quantized endpoint 1 color deltas.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input0 The packed endpoint 0 color.
|
||||
* @param input1 The packed endpoint 1 color deltas.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void rgba_delta_unpack(
|
||||
vint4 input0q,
|
||||
vint4 input1q,
|
||||
quant_method quant_level,
|
||||
vint4 input0,
|
||||
vint4 input1,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
// Unquantize color endpoints
|
||||
vint4 input0 = unquant_color(quant_level, input0q);
|
||||
vint4 input1 = unquant_color(quant_level, input1q);
|
||||
|
||||
// Perform bit-transfer
|
||||
input0 = input0 | lsl<1>(input1 & 0x80);
|
||||
input1 = input1 & 0x7F;
|
||||
vmask4 mask = (input1 & 0x40) != vint4::zero();
|
||||
input1 = select(input1, input1 - 0x80, mask);
|
||||
|
||||
// Scale
|
||||
input0 = asr<1>(input0);
|
||||
input1 = asr<1>(input1);
|
||||
// Apply bit transfer
|
||||
bit_transfer_signed(input1, input0);
|
||||
|
||||
// Apply blue-uncontraction if needed
|
||||
int rgb_sum = hadd_rgb_s(input1);
|
||||
|
@ -126,20 +76,18 @@ static void rgba_delta_unpack(
|
|||
*
|
||||
* Output alpha set to 255.
|
||||
*
|
||||
* @param input0q The raw quantized endpoint 0 color.
|
||||
* @param input1q The raw quantized endpoint 1 color deltas.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input0 The packed endpoint 0 color.
|
||||
* @param input1 The packed endpoint 1 color deltas.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void rgb_delta_unpack(
|
||||
vint4 input0q,
|
||||
vint4 input1q,
|
||||
quant_method quant_level,
|
||||
vint4 input0,
|
||||
vint4 input1,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
rgba_delta_unpack(input0q, input1q, quant_level, output0, output1);
|
||||
rgba_delta_unpack(input0, input1, output0, output1);
|
||||
output0.set_lane<3>(255);
|
||||
output1.set_lane<3>(255);
|
||||
}
|
||||
|
@ -147,23 +95,17 @@ static void rgb_delta_unpack(
|
|||
/**
|
||||
* @brief Unpack an LDR RGBA color that uses direct encoding.
|
||||
*
|
||||
* @param input0q The raw quantized endpoint 0 color.
|
||||
* @param input1q The raw quantized endpoint 1 color.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input0 The packed endpoint 0 color.
|
||||
* @param input1 The packed endpoint 1 color.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void rgba_unpack(
|
||||
vint4 input0q,
|
||||
vint4 input1q,
|
||||
quant_method quant_level,
|
||||
vint4 input0,
|
||||
vint4 input1,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
// Unquantize color endpoints
|
||||
vint4 input0 = unquant_color(quant_level, input0q);
|
||||
vint4 input1 = unquant_color(quant_level, input1q);
|
||||
|
||||
// Apply blue-uncontraction if needed
|
||||
if (hadd_rgb_s(input0) > hadd_rgb_s(input1))
|
||||
{
|
||||
|
@ -181,20 +123,18 @@ static void rgba_unpack(
|
|||
*
|
||||
* Output alpha set to 255.
|
||||
*
|
||||
* @param input0q The raw quantized endpoint 0 color.
|
||||
* @param input1q The raw quantized endpoint 1 color.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input0 The packed endpoint 0 color.
|
||||
* @param input1 The packed endpoint 1 color.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void rgb_unpack(
|
||||
vint4 input0q,
|
||||
vint4 input1q,
|
||||
quant_method quant_level,
|
||||
vint4 input0,
|
||||
vint4 input1,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
rgba_unpack(input0q, input1q, quant_level, output0, output1);
|
||||
rgba_unpack(input0, input1, output0, output1);
|
||||
output0.set_lane<3>(255);
|
||||
output1.set_lane<3>(255);
|
||||
}
|
||||
|
@ -204,31 +144,24 @@ static void rgb_unpack(
|
|||
*
|
||||
* Note only the RGB channels use the scaled encoding, alpha uses direct.
|
||||
*
|
||||
* @param input0q The raw quantized endpoint 0 color.
|
||||
* @param alpha1q The raw quantized endpoint 1 alpha value.
|
||||
* @param scaleq The raw quantized scale.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input0 The packed endpoint 0 color.
|
||||
* @param alpha1 The packed endpoint 1 alpha value.
|
||||
* @param scale The packed quantized scale.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void rgb_scale_alpha_unpack(
|
||||
vint4 input0q,
|
||||
uint8_t alpha1q,
|
||||
uint8_t scaleq,
|
||||
quant_method quant_level,
|
||||
vint4 input0,
|
||||
uint8_t alpha1,
|
||||
uint8_t scale,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
// Unquantize color endpoints
|
||||
vint4 input = unquant_color(quant_level, input0q);
|
||||
uint8_t alpha1 = unquant_color(quant_level, alpha1q);
|
||||
uint8_t scale = unquant_color(quant_level, scaleq);
|
||||
|
||||
output1 = input;
|
||||
output1 = input0;
|
||||
output1.set_lane<3>(alpha1);
|
||||
|
||||
output0 = asr<8>(input * scale);
|
||||
output0.set_lane<3>(input.lane<3>());
|
||||
output0 = asr<8>(input0 * scale);
|
||||
output0.set_lane<3>(input0.lane<3>());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,26 +169,21 @@ static void rgb_scale_alpha_unpack(
|
|||
*
|
||||
* Output alpha is 255.
|
||||
*
|
||||
* @param input0q The raw quantized endpoint 0 color.
|
||||
* @param scaleq The raw quantized scale.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input0 The packed endpoint 0 color.
|
||||
* @param scale The packed scale.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void rgb_scale_unpack(
|
||||
vint4 input0q,
|
||||
int scaleq,
|
||||
quant_method quant_level,
|
||||
vint4 input0,
|
||||
int scale,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
vint4 input = unquant_color(quant_level, input0q);
|
||||
int scale = unquant_color(quant_level, scaleq);
|
||||
|
||||
output1 = input;
|
||||
output1 = input0;
|
||||
output1.set_lane<3>(255);
|
||||
|
||||
output0 = asr<8>(input * scale);
|
||||
output0 = asr<8>(input0 * scale);
|
||||
output0.set_lane<3>(255);
|
||||
}
|
||||
|
||||
|
@ -264,19 +192,17 @@ static void rgb_scale_unpack(
|
|||
*
|
||||
* Output alpha is 255.
|
||||
*
|
||||
* @param input The raw quantized endpoints.
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints.
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void luminance_unpack(
|
||||
const uint8_t input[2],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int lum0 = unquant_color(quant_level, input[0]);
|
||||
int lum1 = unquant_color(quant_level, input[1]);
|
||||
int lum0 = input[0];
|
||||
int lum1 = input[1];
|
||||
output0 = vint4(lum0, lum0, lum0, 255);
|
||||
output1 = vint4(lum1, lum1, lum1, 255);
|
||||
}
|
||||
|
@ -286,19 +212,17 @@ static void luminance_unpack(
|
|||
*
|
||||
* Output alpha is 255.
|
||||
*
|
||||
* @param input The raw quantized endpoints (L0, L1).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (L0, L1).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void luminance_delta_unpack(
|
||||
const uint8_t input[2],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int v0 = unquant_color(quant_level, input[0]);
|
||||
int v1 = unquant_color(quant_level, input[1]);
|
||||
int v0 = input[0];
|
||||
int v1 = input[1];
|
||||
int l0 = (v0 >> 2) | (v1 & 0xC0);
|
||||
int l1 = l0 + (v1 & 0x3F);
|
||||
|
||||
|
@ -311,21 +235,19 @@ static void luminance_delta_unpack(
|
|||
/**
|
||||
* @brief Unpack an LDR LA color that uses direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (L0, L1, A0, A1).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (L0, L1, A0, A1).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void luminance_alpha_unpack(
|
||||
const uint8_t input[4],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int lum0 = unquant_color(quant_level, input[0]);
|
||||
int lum1 = unquant_color(quant_level, input[1]);
|
||||
int alpha0 = unquant_color(quant_level, input[2]);
|
||||
int alpha1 = unquant_color(quant_level, input[3]);
|
||||
int lum0 = input[0];
|
||||
int lum1 = input[1];
|
||||
int alpha0 = input[2];
|
||||
int alpha1 = input[3];
|
||||
output0 = vint4(lum0, lum0, lum0, alpha0);
|
||||
output1 = vint4(lum1, lum1, lum1, alpha1);
|
||||
}
|
||||
|
@ -333,30 +255,34 @@ static void luminance_alpha_unpack(
|
|||
/**
|
||||
* @brief Unpack an LDR LA color that uses delta encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (L0, L1, A0, A1).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (L0, L1, A0, A1).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void luminance_alpha_delta_unpack(
|
||||
const uint8_t input[4],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int lum0 = unquant_color(quant_level, input[0]);
|
||||
int lum1 = unquant_color(quant_level, input[1]);
|
||||
int alpha0 = unquant_color(quant_level, input[2]);
|
||||
int alpha1 = unquant_color(quant_level, input[3]);
|
||||
int lum0 = input[0];
|
||||
int lum1 = input[1];
|
||||
int alpha0 = input[2];
|
||||
int alpha1 = input[3];
|
||||
|
||||
lum0 |= (lum1 & 0x80) << 1;
|
||||
alpha0 |= (alpha1 & 0x80) << 1;
|
||||
lum1 &= 0x7F;
|
||||
alpha1 &= 0x7F;
|
||||
|
||||
if (lum1 & 0x40)
|
||||
{
|
||||
lum1 -= 0x80;
|
||||
}
|
||||
|
||||
if (alpha1 & 0x40)
|
||||
{
|
||||
alpha1 -= 0x80;
|
||||
}
|
||||
|
||||
lum0 >>= 1;
|
||||
lum1 >>= 1;
|
||||
|
@ -375,21 +301,19 @@ static void luminance_alpha_delta_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR RGB + offset encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_rgbo_unpack(
|
||||
const uint8_t input[4],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int v0 = unquant_color(quant_level, input[0]);
|
||||
int v1 = unquant_color(quant_level, input[1]);
|
||||
int v2 = unquant_color(quant_level, input[2]);
|
||||
int v3 = unquant_color(quant_level, input[3]);
|
||||
int v0 = input[0];
|
||||
int v1 = input[1];
|
||||
int v2 = input[2];
|
||||
int v3 = input[3];
|
||||
|
||||
int modeval = ((v0 & 0xC0) >> 6) | (((v1 & 0x80) >> 7) << 2) | (((v2 & 0x80) >> 7) << 3);
|
||||
|
||||
|
@ -527,24 +451,22 @@ static void hdr_rgbo_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR RGB direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_rgb_unpack(
|
||||
const uint8_t input[6],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
|
||||
int v0 = unquant_color(quant_level, input[0]);
|
||||
int v1 = unquant_color(quant_level, input[1]);
|
||||
int v2 = unquant_color(quant_level, input[2]);
|
||||
int v3 = unquant_color(quant_level, input[3]);
|
||||
int v4 = unquant_color(quant_level, input[4]);
|
||||
int v5 = unquant_color(quant_level, input[5]);
|
||||
int v0 = input[0];
|
||||
int v1 = input[1];
|
||||
int v2 = input[2];
|
||||
int v3 = input[3];
|
||||
int v4 = input[4];
|
||||
int v5 = input[5];
|
||||
|
||||
// extract all the fixed-placement bitfields
|
||||
int modeval = ((v1 & 0x80) >> 7) | (((v2 & 0x80) >> 7) << 1) | (((v3 & 0x80) >> 7) << 2);
|
||||
|
@ -695,21 +617,19 @@ static void hdr_rgb_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR RGB + LDR A direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_rgb_ldr_alpha_unpack(
|
||||
const uint8_t input[8],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
hdr_rgb_unpack(input, quant_level, output0, output1);
|
||||
hdr_rgb_unpack(input, output0, output1);
|
||||
|
||||
int v6 = unquant_color(quant_level, input[6]);
|
||||
int v7 = unquant_color(quant_level, input[7]);
|
||||
int v6 = input[6];
|
||||
int v7 = input[7];
|
||||
output0.set_lane<3>(v6);
|
||||
output1.set_lane<3>(v7);
|
||||
}
|
||||
|
@ -717,19 +637,17 @@ static void hdr_rgb_ldr_alpha_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR L (small range) direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_luminance_small_range_unpack(
|
||||
const uint8_t input[2],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int v0 = unquant_color(quant_level, input[0]);
|
||||
int v1 = unquant_color(quant_level, input[1]);
|
||||
int v0 = input[0];
|
||||
int v1 = input[1];
|
||||
|
||||
int y0, y1;
|
||||
if (v0 & 0x80)
|
||||
|
@ -745,7 +663,9 @@ static void hdr_luminance_small_range_unpack(
|
|||
|
||||
y1 += y0;
|
||||
if (y1 > 0xFFF)
|
||||
{
|
||||
y1 = 0xFFF;
|
||||
}
|
||||
|
||||
output0 = vint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
|
||||
output1 = vint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
|
||||
|
@ -754,19 +674,17 @@ static void hdr_luminance_small_range_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR L (large range) direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_luminance_large_range_unpack(
|
||||
const uint8_t input[2],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
int v0 = unquant_color(quant_level, input[0]);
|
||||
int v1 = unquant_color(quant_level, input[1]);
|
||||
int v0 = input[0];
|
||||
int v1 = input[1];
|
||||
|
||||
int y0, y1;
|
||||
if (v1 >= v0)
|
||||
|
@ -787,20 +705,18 @@ static void hdr_luminance_large_range_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR A direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_alpha_unpack(
|
||||
const uint8_t input[2],
|
||||
quant_method quant_level,
|
||||
int& output0,
|
||||
int& output1
|
||||
) {
|
||||
|
||||
int v6 = unquant_color(quant_level, input[0]);
|
||||
int v7 = unquant_color(quant_level, input[1]);
|
||||
int v6 = input[0];
|
||||
int v7 = input[1];
|
||||
|
||||
int selector = ((v6 >> 7) & 1) | ((v7 >> 6) & 2);
|
||||
v6 &= 0x7F;
|
||||
|
@ -821,9 +737,13 @@ static void hdr_alpha_unpack(
|
|||
v7 += v6;
|
||||
|
||||
if (v7 < 0)
|
||||
{
|
||||
v7 = 0;
|
||||
}
|
||||
else if (v7 > 0xFFF)
|
||||
{
|
||||
v7 = 0xFFF;
|
||||
}
|
||||
|
||||
output0 = v6;
|
||||
output1 = v7;
|
||||
|
@ -836,21 +756,19 @@ static void hdr_alpha_unpack(
|
|||
/**
|
||||
* @brief Unpack an HDR RGBA direct encoding.
|
||||
*
|
||||
* @param input The raw quantized endpoints (packed and modal).
|
||||
* @param quant_level The quantization level to use.
|
||||
* @param[out] output0 The unpacked and unquantized endpoint 0 color.
|
||||
* @param[out] output1 The unpacked and unquantized endpoint 1 color.
|
||||
* @param input The packed endpoints (packed and modal).
|
||||
* @param[out] output0 The unpacked endpoint 0 color.
|
||||
* @param[out] output1 The unpacked endpoint 1 color.
|
||||
*/
|
||||
static void hdr_rgb_hdr_alpha_unpack(
|
||||
const uint8_t input[8],
|
||||
quant_method quant_level,
|
||||
vint4& output0,
|
||||
vint4& output1
|
||||
) {
|
||||
hdr_rgb_unpack(input, quant_level, output0, output1);
|
||||
hdr_rgb_unpack(input, output0, output1);
|
||||
|
||||
int alpha0, alpha1;
|
||||
hdr_alpha_unpack(input + 6, quant_level, alpha0, alpha1);
|
||||
hdr_alpha_unpack(input + 6, alpha0, alpha1);
|
||||
|
||||
output0.set_lane<3>(alpha0);
|
||||
output1.set_lane<3>(alpha1);
|
||||
|
@ -860,7 +778,6 @@ static void hdr_rgb_hdr_alpha_unpack(
|
|||
void unpack_color_endpoints(
|
||||
astcenc_profile decode_mode,
|
||||
int format,
|
||||
quant_method quant_level,
|
||||
const uint8_t* input,
|
||||
bool& rgb_hdr,
|
||||
bool& alpha_hdr,
|
||||
|
@ -876,38 +793,38 @@ void unpack_color_endpoints(
|
|||
switch (format)
|
||||
{
|
||||
case FMT_LUMINANCE:
|
||||
luminance_unpack(input, quant_level, output0, output1);
|
||||
luminance_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_LUMINANCE_DELTA:
|
||||
luminance_delta_unpack(input, quant_level, output0, output1);
|
||||
luminance_delta_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_HDR_LUMINANCE_SMALL_RANGE:
|
||||
rgb_hdr = true;
|
||||
alpha_hdr_default = true;
|
||||
hdr_luminance_small_range_unpack(input, quant_level, output0, output1);
|
||||
hdr_luminance_small_range_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_HDR_LUMINANCE_LARGE_RANGE:
|
||||
rgb_hdr = true;
|
||||
alpha_hdr_default = true;
|
||||
hdr_luminance_large_range_unpack(input, quant_level, output0, output1);
|
||||
hdr_luminance_large_range_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_LUMINANCE_ALPHA:
|
||||
luminance_alpha_unpack(input, quant_level, output0, output1);
|
||||
luminance_alpha_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_LUMINANCE_ALPHA_DELTA:
|
||||
luminance_alpha_delta_unpack(input, quant_level, output0, output1);
|
||||
luminance_alpha_delta_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_RGB_SCALE:
|
||||
{
|
||||
vint4 input0q(input[0], input[1], input[2], 0);
|
||||
uint8_t scale = input[3];
|
||||
rgb_scale_unpack(input0q, scale, quant_level, output0, output1);
|
||||
rgb_scale_unpack(input0q, scale, output0, output1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -916,21 +833,21 @@ void unpack_color_endpoints(
|
|||
vint4 input0q(input[0], input[1], input[2], input[4]);
|
||||
uint8_t alpha1q = input[5];
|
||||
uint8_t scaleq = input[3];
|
||||
rgb_scale_alpha_unpack(input0q, alpha1q, scaleq, quant_level, output0, output1);
|
||||
rgb_scale_alpha_unpack(input0q, alpha1q, scaleq, output0, output1);
|
||||
}
|
||||
break;
|
||||
|
||||
case FMT_HDR_RGB_SCALE:
|
||||
rgb_hdr = true;
|
||||
alpha_hdr_default = true;
|
||||
hdr_rgbo_unpack(input, quant_level,output0, output1);
|
||||
hdr_rgbo_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_RGB:
|
||||
{
|
||||
vint4 input0q(input[0], input[2], input[4], 0);
|
||||
vint4 input1q(input[1], input[3], input[5], 0);
|
||||
rgb_unpack(input0q, input1q, quant_level, output0, output1);
|
||||
rgb_unpack(input0q, input1q, output0, output1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -938,21 +855,21 @@ void unpack_color_endpoints(
|
|||
{
|
||||
vint4 input0q(input[0], input[2], input[4], 0);
|
||||
vint4 input1q(input[1], input[3], input[5], 0);
|
||||
rgb_delta_unpack(input0q, input1q, quant_level, output0, output1);
|
||||
rgb_delta_unpack(input0q, input1q, output0, output1);
|
||||
}
|
||||
break;
|
||||
|
||||
case FMT_HDR_RGB:
|
||||
rgb_hdr = true;
|
||||
alpha_hdr_default = true;
|
||||
hdr_rgb_unpack(input, quant_level, output0, output1);
|
||||
hdr_rgb_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_RGBA:
|
||||
{
|
||||
vint4 input0q(input[0], input[2], input[4], input[6]);
|
||||
vint4 input1q(input[1], input[3], input[5], input[7]);
|
||||
rgba_unpack(input0q, input1q, quant_level, output0, output1);
|
||||
rgba_unpack(input0q, input1q, output0, output1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -960,19 +877,19 @@ void unpack_color_endpoints(
|
|||
{
|
||||
vint4 input0q(input[0], input[2], input[4], input[6]);
|
||||
vint4 input1q(input[1], input[3], input[5], input[7]);
|
||||
rgba_delta_unpack(input0q, input1q, quant_level, output0, output1);
|
||||
rgba_delta_unpack(input0q, input1q, output0, output1);
|
||||
}
|
||||
break;
|
||||
|
||||
case FMT_HDR_RGB_LDR_ALPHA:
|
||||
rgb_hdr = true;
|
||||
hdr_rgb_ldr_alpha_unpack(input, quant_level, output0, output1);
|
||||
hdr_rgb_ldr_alpha_unpack(input, output0, output1);
|
||||
break;
|
||||
|
||||
case FMT_HDR_RGBA:
|
||||
rgb_hdr = true;
|
||||
alpha_hdr = true;
|
||||
hdr_rgb_hdr_alpha_unpack(input, quant_level, output0, output1);
|
||||
hdr_rgb_hdr_alpha_unpack(input, output0, output1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -82,7 +82,7 @@ static bool realign_weights_undecimated(
|
|||
const quant_and_transfer_table& qat = quant_and_xfer_tables[weight_quant_level];
|
||||
|
||||
unsigned int max_plane = bm.is_dual_plane;
|
||||
int plane2_component = bm.is_dual_plane ? scb.plane2_component : -1;
|
||||
int plane2_component = scb.plane2_component;
|
||||
vmask4 plane_mask = vint4::lane_id() == vint4(plane2_component);
|
||||
|
||||
// Decode the color endpoints
|
||||
|
@ -99,7 +99,6 @@ static bool realign_weights_undecimated(
|
|||
{
|
||||
unpack_color_endpoints(decode_mode,
|
||||
scb.color_formats[pa_idx],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[pa_idx],
|
||||
rgb_hdr, alpha_hdr,
|
||||
endpnt0[pa_idx],
|
||||
|
@ -207,7 +206,7 @@ static bool realign_weights_decimated(
|
|||
assert(weight_count != bsd.texel_count);
|
||||
|
||||
unsigned int max_plane = bm.is_dual_plane;
|
||||
int plane2_component = bm.is_dual_plane ? scb.plane2_component : -1;
|
||||
int plane2_component = scb.plane2_component;
|
||||
vmask4 plane_mask = vint4::lane_id() == vint4(plane2_component);
|
||||
|
||||
// Decode the color endpoints
|
||||
|
@ -225,7 +224,6 @@ static bool realign_weights_decimated(
|
|||
{
|
||||
unpack_color_endpoints(decode_mode,
|
||||
scb.color_formats[pa_idx],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[pa_idx],
|
||||
rgb_hdr, alpha_hdr,
|
||||
endpnt0[pa_idx],
|
||||
|
@ -279,17 +277,14 @@ static bool realign_weights_decimated(
|
|||
promise(texels_to_evaluate > 0);
|
||||
for (unsigned int te_idx = 0; te_idx < texels_to_evaluate; te_idx++)
|
||||
{
|
||||
unsigned int texel = di.weight_texel[te_idx][we_idx];
|
||||
unsigned int texel = di.weight_texels_tr[te_idx][we_idx];
|
||||
|
||||
const uint8_t *texel_weights = di.texel_weights_texel[we_idx][te_idx];
|
||||
const float *texel_weights_float = di.texel_weights_float_texel[we_idx][te_idx];
|
||||
float tw_base = di.texel_contrib_for_weight[te_idx][we_idx];
|
||||
|
||||
float tw_base = texel_weights_float[0];
|
||||
|
||||
float weight_base = (uqw_base * tw_base
|
||||
+ uq_weightsf[texel_weights[1]] * texel_weights_float[1])
|
||||
+ (uq_weightsf[texel_weights[2]] * texel_weights_float[2]
|
||||
+ uq_weightsf[texel_weights[3]] * texel_weights_float[3]);
|
||||
float weight_base = (uq_weightsf[di.texel_weights_tr[0][texel]] * di.texel_weight_contribs_float_tr[0][texel]
|
||||
+ uq_weightsf[di.texel_weights_tr[1][texel]] * di.texel_weight_contribs_float_tr[1][texel])
|
||||
+ (uq_weightsf[di.texel_weights_tr[2][texel]] * di.texel_weight_contribs_float_tr[2][texel]
|
||||
+ uq_weightsf[di.texel_weights_tr[3][texel]] * di.texel_weight_contribs_float_tr[3][texel]);
|
||||
|
||||
// Ideally this is integer rounded, but IQ gain it isn't worth the overhead
|
||||
// float weight = astc::flt_rd(weight_base + 0.5f);
|
||||
|
@ -424,11 +419,7 @@ static float compress_symbolic_block_for_partition_1plane(
|
|||
|
||||
// For each mode, use the angular method to compute a shift
|
||||
compute_angular_endpoints_1plane(
|
||||
config.tune_low_weight_count_limit,
|
||||
only_always, bsd,
|
||||
dec_weights_ideal,
|
||||
max_weight_quant,
|
||||
tmpbuf);
|
||||
only_always, bsd, dec_weights_ideal, max_weight_quant, tmpbuf);
|
||||
|
||||
float* weight_low_value = tmpbuf.weight_low_value1;
|
||||
float* weight_high_value = tmpbuf.weight_high_value1;
|
||||
|
@ -448,7 +439,7 @@ static float compress_symbolic_block_for_partition_1plane(
|
|||
unsigned int max_block_modes = only_always ? bsd.block_mode_count_1plane_always
|
||||
: bsd.block_mode_count_1plane_selected;
|
||||
promise(max_block_modes > 0);
|
||||
for (unsigned int i = 0; i < max_block_modes; ++i)
|
||||
for (unsigned int i = 0; i < max_block_modes; i++)
|
||||
{
|
||||
const block_mode& bm = bsd.block_modes[i];
|
||||
|
||||
|
@ -628,12 +619,12 @@ static float compress_symbolic_block_for_partition_1plane(
|
|||
trace_add_data("error_prerealign", errorval);
|
||||
best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode);
|
||||
|
||||
// Average refinement improvement is 3.5% per iteration (allow 5%), but the first
|
||||
// iteration can help more so we give it a extra 10% leeway. Use this knowledge to
|
||||
// Average refinement improvement is 3.5% per iteration (allow 4.5%), but the first
|
||||
// iteration can help more so we give it a extra 8% leeway. Use this knowledge to
|
||||
// drive a heuristic to skip blocks that are unlikely to catch up with the best
|
||||
// block we have already.
|
||||
unsigned int iters_remaining = config.tune_refinement_limit - l;
|
||||
float threshold = (0.05f * static_cast<float>(iters_remaining)) + 1.1f;
|
||||
float threshold = (0.045f * static_cast<float>(iters_remaining)) + 1.08f;
|
||||
if (errorval > (threshold * best_errorval_in_scb))
|
||||
{
|
||||
break;
|
||||
|
@ -678,10 +669,10 @@ static float compress_symbolic_block_for_partition_1plane(
|
|||
best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode);
|
||||
|
||||
// Average refinement improvement is 3.5% per iteration, so skip blocks that are
|
||||
// unlikely to catch up with the best block we have already. Assume a 5% per step to
|
||||
// unlikely to catch up with the best block we have already. Assume a 4.5% per step to
|
||||
// give benefit of the doubt ...
|
||||
unsigned int iters_remaining = config.tune_refinement_limit - 1 - l;
|
||||
float threshold = (0.05f * static_cast<float>(iters_remaining)) + 1.0f;
|
||||
float threshold = (0.045f * static_cast<float>(iters_remaining)) + 1.0f;
|
||||
if (errorval > (threshold * best_errorval_in_scb))
|
||||
{
|
||||
break;
|
||||
|
@ -795,9 +786,7 @@ static float compress_symbolic_block_for_partition_2planes(
|
|||
float min_wt_cutoff2 = hmin_s(select(err_max, min_ep2, err_mask));
|
||||
|
||||
compute_angular_endpoints_2planes(
|
||||
config.tune_low_weight_count_limit,
|
||||
bsd, dec_weights_ideal, max_weight_quant,
|
||||
tmpbuf);
|
||||
bsd, dec_weights_ideal, max_weight_quant, tmpbuf);
|
||||
|
||||
// For each mode (which specifies a decimation and a quantization):
|
||||
// * Compute number of bits needed for the quantized weights
|
||||
|
@ -964,12 +953,12 @@ static float compress_symbolic_block_for_partition_2planes(
|
|||
trace_add_data("error_prerealign", errorval);
|
||||
best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode);
|
||||
|
||||
// Average refinement improvement is 3.5% per iteration (allow 5%), but the first
|
||||
// iteration can help more so we give it a extra 10% leeway. Use this knowledge to
|
||||
// Average refinement improvement is 3.5% per iteration (allow 4.5%), but the first
|
||||
// iteration can help more so we give it a extra 8% leeway. Use this knowledge to
|
||||
// drive a heuristic to skip blocks that are unlikely to catch up with the best
|
||||
// block we have already.
|
||||
unsigned int iters_remaining = config.tune_refinement_limit - l;
|
||||
float threshold = (0.05f * static_cast<float>(iters_remaining)) + 1.1f;
|
||||
float threshold = (0.045f * static_cast<float>(iters_remaining)) + 1.08f;
|
||||
if (errorval > (threshold * best_errorval_in_scb))
|
||||
{
|
||||
break;
|
||||
|
@ -1015,10 +1004,10 @@ static float compress_symbolic_block_for_partition_2planes(
|
|||
best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode);
|
||||
|
||||
// Average refinement improvement is 3.5% per iteration, so skip blocks that are
|
||||
// unlikely to catch up with the best block we have already. Assume a 5% per step to
|
||||
// unlikely to catch up with the best block we have already. Assume a 4.5% per step to
|
||||
// give benefit of the doubt ...
|
||||
unsigned int iters_remaining = config.tune_refinement_limit - 1 - l;
|
||||
float threshold = (0.05f * static_cast<float>(iters_remaining)) + 1.0f;
|
||||
float threshold = (0.045f * static_cast<float>(iters_remaining)) + 1.0f;
|
||||
if (errorval > (threshold * best_errorval_in_scb))
|
||||
{
|
||||
break;
|
||||
|
@ -1130,12 +1119,13 @@ static float prepare_block_statistics(
|
|||
|
||||
aa_var -= as * (as * rpt);
|
||||
|
||||
rg_cov *= astc::rsqrt(astc::max(rr_var * gg_var, 1e-30f));
|
||||
rb_cov *= astc::rsqrt(astc::max(rr_var * bb_var, 1e-30f));
|
||||
ra_cov *= astc::rsqrt(astc::max(rr_var * aa_var, 1e-30f));
|
||||
gb_cov *= astc::rsqrt(astc::max(gg_var * bb_var, 1e-30f));
|
||||
ga_cov *= astc::rsqrt(astc::max(gg_var * aa_var, 1e-30f));
|
||||
ba_cov *= astc::rsqrt(astc::max(bb_var * aa_var, 1e-30f));
|
||||
// These will give a NaN if a channel is constant - these are fixed up in the next step
|
||||
rg_cov *= astc::rsqrt(rr_var * gg_var);
|
||||
rb_cov *= astc::rsqrt(rr_var * bb_var);
|
||||
ra_cov *= astc::rsqrt(rr_var * aa_var);
|
||||
gb_cov *= astc::rsqrt(gg_var * bb_var);
|
||||
ga_cov *= astc::rsqrt(gg_var * aa_var);
|
||||
ba_cov *= astc::rsqrt(bb_var * aa_var);
|
||||
|
||||
if (astc::isnan(rg_cov)) rg_cov = 1.0f;
|
||||
if (astc::isnan(rb_cov)) rb_cov = 1.0f;
|
||||
|
@ -1144,7 +1134,7 @@ static float prepare_block_statistics(
|
|||
if (astc::isnan(ga_cov)) ga_cov = 1.0f;
|
||||
if (astc::isnan(ba_cov)) ba_cov = 1.0f;
|
||||
|
||||
float lowest_correlation = astc::min(fabsf(rg_cov), fabsf(rb_cov));
|
||||
float lowest_correlation = astc::min(fabsf(rg_cov), fabsf(rb_cov));
|
||||
lowest_correlation = astc::min(lowest_correlation, fabsf(ra_cov));
|
||||
lowest_correlation = astc::min(lowest_correlation, fabsf(gb_cov));
|
||||
lowest_correlation = astc::min(lowest_correlation, fabsf(ga_cov));
|
||||
|
@ -1197,6 +1187,18 @@ void compress_block(
|
|||
bool block_skip_two_plane = false;
|
||||
int max_partitions = ctx.config.tune_partition_count_limit;
|
||||
|
||||
unsigned int requested_partition_indices[3] {
|
||||
ctx.config.tune_2partition_index_limit,
|
||||
ctx.config.tune_3partition_index_limit,
|
||||
ctx.config.tune_4partition_index_limit
|
||||
};
|
||||
|
||||
unsigned int requested_partition_trials[3] {
|
||||
ctx.config.tune_2partitioning_candidate_limit,
|
||||
ctx.config.tune_3partitioning_candidate_limit,
|
||||
ctx.config.tune_4partitioning_candidate_limit
|
||||
};
|
||||
|
||||
#if defined(ASTCENC_DIAGNOSTICS)
|
||||
// Do this early in diagnostic builds so we can dump uniform metrics
|
||||
// for every block. Do it later in release builds to avoid redundant work!
|
||||
|
@ -1274,13 +1276,13 @@ void compress_block(
|
|||
// compression and slightly reduces image quality.
|
||||
|
||||
float errorval_mult[2] {
|
||||
1.0f / ctx.config.tune_mode0_mse_overshoot,
|
||||
1.0f / ctx.config.tune_mse_overshoot,
|
||||
1.0f
|
||||
};
|
||||
|
||||
static const float errorval_overshoot = 1.0f / ctx.config.tune_refinement_mse_overshoot;
|
||||
static const float errorval_overshoot = 1.0f / ctx.config.tune_mse_overshoot;
|
||||
|
||||
// Only enable MODE0 fast path (trial 0) if 2D and more than 25 texels
|
||||
// Only enable MODE0 fast path (trial 0) if 2D, and more than 25 texels
|
||||
int start_trial = 1;
|
||||
if ((bsd.texel_count >= TUNE_MIN_TEXELS_MODE0_FASTPATH) && (bsd.zdim == 1))
|
||||
{
|
||||
|
@ -1351,7 +1353,7 @@ void compress_block(
|
|||
|
||||
// If attempting two planes is much worse than the best one plane result
|
||||
// then further two plane searches are unlikely to help so move on ...
|
||||
if (errorval > (best_errorvals_for_pcount[0] * 2.0f))
|
||||
if (errorval > (best_errorvals_for_pcount[0] * 1.85f))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1366,13 +1368,19 @@ void compress_block(
|
|||
// Find best blocks for 2, 3 and 4 partitions
|
||||
for (int partition_count = 2; partition_count <= max_partitions; partition_count++)
|
||||
{
|
||||
unsigned int partition_indices[2] { 0 };
|
||||
unsigned int partition_indices[TUNE_MAX_PARTITIONING_CANDIDATES];
|
||||
|
||||
find_best_partition_candidates(bsd, blk, partition_count,
|
||||
ctx.config.tune_partition_index_limit,
|
||||
partition_indices);
|
||||
unsigned int requested_indices = requested_partition_indices[partition_count - 2];
|
||||
|
||||
for (unsigned int i = 0; i < 2; i++)
|
||||
unsigned int requested_trials = requested_partition_trials[partition_count - 2];
|
||||
requested_trials = astc::min(requested_trials, requested_indices);
|
||||
|
||||
unsigned int actual_trials = find_best_partition_candidates(
|
||||
bsd, blk, partition_count, requested_indices, partition_indices, requested_trials);
|
||||
|
||||
float best_error_in_prev = best_errorvals_for_pcount[partition_count - 2];
|
||||
|
||||
for (unsigned int i = 0; i < actual_trials; i++)
|
||||
{
|
||||
TRACE_NODE(node1, "pass");
|
||||
trace_add_data("partition_count", partition_count);
|
||||
|
@ -1387,6 +1395,19 @@ void compress_block(
|
|||
scb, tmpbuf, quant_limit);
|
||||
|
||||
best_errorvals_for_pcount[partition_count - 1] = astc::min(best_errorvals_for_pcount[partition_count - 1], errorval);
|
||||
|
||||
// If using N partitions doesn't improve much over using N-1 partitions then skip trying
|
||||
// N+1. Error can dramatically improve if the data is correlated or non-correlated and
|
||||
// aligns with a partitioning that suits that encoding, so for this inner loop check add
|
||||
// a large error scale because the "other" trial could be a lot better.
|
||||
float best_error = best_errorvals_for_pcount[partition_count - 1];
|
||||
float best_error_scale = exit_thresholds_for_pcount[partition_count - 1] * 1.85f;
|
||||
if (best_error > (best_error_in_prev * best_error_scale))
|
||||
{
|
||||
trace_add_data("skip", "tune_partition_early_out_limit_factor");
|
||||
goto END_OF_TESTS;
|
||||
}
|
||||
|
||||
if (errorval < error_threshold)
|
||||
{
|
||||
trace_add_data("exit", "quality hit");
|
||||
|
@ -1396,7 +1417,6 @@ void compress_block(
|
|||
|
||||
// If using N partitions doesn't improve much over using N-1 partitions then skip trying N+1
|
||||
float best_error = best_errorvals_for_pcount[partition_count - 1];
|
||||
float best_error_in_prev = best_errorvals_for_pcount[partition_count - 2];
|
||||
float best_error_scale = exit_thresholds_for_pcount[partition_count - 1];
|
||||
if (best_error > (best_error_in_prev * best_error_scale))
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -121,8 +121,8 @@ void unpack_weights(
|
|||
promise(max_weight_count > 0);
|
||||
for (int j = 0; j < max_weight_count; j++)
|
||||
{
|
||||
vint texel_weights(di.texel_weights_4t[j] + i);
|
||||
vint texel_weights_int(di.texel_weights_int_4t[j] + i);
|
||||
vint texel_weights(di.texel_weights_tr[j] + i);
|
||||
vint texel_weights_int(di.texel_weight_contribs_int_tr[j] + i);
|
||||
|
||||
summed_value += vtable_8bt_32bi(tab0p, tab1p, tab2p, tab3p, texel_weights) * texel_weights_int;
|
||||
}
|
||||
|
@ -156,8 +156,8 @@ void unpack_weights(
|
|||
promise(max_weight_count > 0);
|
||||
for (int j = 0; j < max_weight_count; j++)
|
||||
{
|
||||
vint texel_weights(di.texel_weights_4t[j] + i);
|
||||
vint texel_weights_int(di.texel_weights_int_4t[j] + i);
|
||||
vint texel_weights(di.texel_weights_tr[j] + i);
|
||||
vint texel_weights_int(di.texel_weight_contribs_int_tr[j] + i);
|
||||
|
||||
sum_plane1 += vtable_8bt_32bi(tab0_plane1p, tab1_plane1p, texel_weights) * texel_weights_int;
|
||||
sum_plane2 += vtable_8bt_32bi(tab0_plane2p, tab1_plane2p, texel_weights) * texel_weights_int;
|
||||
|
@ -286,7 +286,7 @@ void decompress_symbolic_block(
|
|||
unpack_weights(bsd, scb, di, is_dual_plane, plane1_weights, plane2_weights);
|
||||
|
||||
// Now that we have endpoint colors and weights, we can unpack texel colors
|
||||
int plane2_component = is_dual_plane ? scb.plane2_component : -1;
|
||||
int plane2_component = scb.plane2_component;
|
||||
vmask4 plane2_mask = vint4::lane_id() == vint4(plane2_component);
|
||||
|
||||
for (int i = 0; i < partition_count; i++)
|
||||
|
@ -299,7 +299,6 @@ void decompress_symbolic_block(
|
|||
|
||||
unpack_color_endpoints(decode_mode,
|
||||
scb.color_formats[i],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[i],
|
||||
rgb_lns, a_lns,
|
||||
ep0, ep1);
|
||||
|
@ -362,7 +361,6 @@ float compute_symbolic_block_difference_2plane(
|
|||
|
||||
unpack_color_endpoints(config.profile,
|
||||
scb.color_formats[0],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[0],
|
||||
rgb_lns, a_lns,
|
||||
ep0, ep1);
|
||||
|
@ -457,7 +455,6 @@ float compute_symbolic_block_difference_1plane(
|
|||
|
||||
unpack_color_endpoints(config.profile,
|
||||
scb.color_formats[i],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[i],
|
||||
rgb_lns, a_lns,
|
||||
ep0, ep1);
|
||||
|
@ -546,7 +543,6 @@ float compute_symbolic_block_difference_1plane_1partition(
|
|||
|
||||
unpack_color_endpoints(config.profile,
|
||||
scb.color_formats[0],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[0],
|
||||
rgb_lns, a_lns,
|
||||
ep0, ep1);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -40,88 +40,95 @@ struct astcenc_preset_config
|
|||
{
|
||||
float quality;
|
||||
unsigned int tune_partition_count_limit;
|
||||
unsigned int tune_partition_index_limit;
|
||||
unsigned int tune_2partition_index_limit;
|
||||
unsigned int tune_3partition_index_limit;
|
||||
unsigned int tune_4partition_index_limit;
|
||||
unsigned int tune_block_mode_limit;
|
||||
unsigned int tune_refinement_limit;
|
||||
unsigned int tune_candidate_limit;
|
||||
unsigned int tune_2partitioning_candidate_limit;
|
||||
unsigned int tune_3partitioning_candidate_limit;
|
||||
unsigned int tune_4partitioning_candidate_limit;
|
||||
float tune_db_limit_a_base;
|
||||
float tune_db_limit_b_base;
|
||||
float tune_mode0_mse_overshoot;
|
||||
float tune_refinement_mse_overshoot;
|
||||
float tune_mse_overshoot;
|
||||
float tune_2_partition_early_out_limit_factor;
|
||||
float tune_3_partition_early_out_limit_factor;
|
||||
float tune_2_plane_early_out_limit_correlation;
|
||||
unsigned int tune_low_weight_count_limit;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The static quality presets that are built-in for high bandwidth
|
||||
* presets (x < 25 texels per block).
|
||||
* @brief The static presets for high bandwidth encodings (x < 25 texels per block).
|
||||
*/
|
||||
static const std::array<astcenc_preset_config, 5> preset_configs_high {{
|
||||
static const std::array<astcenc_preset_config, 6> preset_configs_high {{
|
||||
{
|
||||
ASTCENC_PRE_FASTEST,
|
||||
2, 10, 43, 2, 2, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.0f, 0.5f, 25
|
||||
2, 10, 6, 4, 43, 2, 2, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.85f
|
||||
}, {
|
||||
ASTCENC_PRE_FAST,
|
||||
3, 14, 55, 3, 3, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.1f, 0.65f, 20
|
||||
3, 18, 10, 8, 55, 3, 3, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.90f
|
||||
}, {
|
||||
ASTCENC_PRE_MEDIUM,
|
||||
4, 28, 76, 3, 3, 95.0f, 70.0f, 2.5f, 2.5f, 1.2f, 1.25f, 0.85f, 16
|
||||
4, 34, 28, 16, 77, 3, 3, 2, 2, 2, 95.0f, 70.0f, 2.5f, 1.1f, 1.05f, 0.95f
|
||||
}, {
|
||||
ASTCENC_PRE_THOROUGH,
|
||||
4, 76, 93, 4, 4, 105.0f, 77.0f, 10.0f, 10.0f, 2.5f, 1.25f, 0.95f, 12
|
||||
4, 82, 60, 30, 94, 4, 4, 3, 2, 2, 105.0f, 77.0f, 10.0f, 1.35f, 1.15f, 0.97f
|
||||
}, {
|
||||
ASTCENC_PRE_VERYTHOROUGH,
|
||||
4, 256, 128, 64, 98, 4, 6, 20, 14, 8, 200.0f, 200.0f, 10.0f, 1.6f, 1.4f, 0.98f
|
||||
}, {
|
||||
ASTCENC_PRE_EXHAUSTIVE,
|
||||
4, 1024, 100, 4, 4, 200.0f, 200.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.99f, 0
|
||||
4, 512, 512, 512, 100, 4, 8, 32, 32, 32, 200.0f, 200.0f, 10.0f, 2.0f, 2.0f, 0.99f
|
||||
}
|
||||
}};
|
||||
|
||||
/**
|
||||
* @brief The static quality presets that are built-in for medium bandwidth
|
||||
* presets (25 <= x < 64 texels per block).
|
||||
* @brief The static presets for medium bandwidth encodings (25 <= x < 64 texels per block).
|
||||
*/
|
||||
static const std::array<astcenc_preset_config, 5> preset_configs_mid {{
|
||||
static const std::array<astcenc_preset_config, 6> preset_configs_mid {{
|
||||
{
|
||||
ASTCENC_PRE_FASTEST,
|
||||
2, 10, 43, 2, 2, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.0f, 0.5f, 20
|
||||
2, 10, 6, 4, 43, 2, 2, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.80f
|
||||
}, {
|
||||
ASTCENC_PRE_FAST,
|
||||
3, 15, 55, 3, 3, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.1f, 0.5f, 16
|
||||
3, 18, 12, 10, 55, 3, 3, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.85f
|
||||
}, {
|
||||
ASTCENC_PRE_MEDIUM,
|
||||
4, 30, 76, 3, 3, 95.0f, 70.0f, 3.0f, 3.0f, 1.2f, 1.25f, 0.75f, 14
|
||||
4, 34, 28, 16, 77, 3, 3, 2, 2, 2, 95.0f, 70.0f, 3.0f, 1.1f, 1.05f, 0.90f
|
||||
}, {
|
||||
ASTCENC_PRE_THOROUGH,
|
||||
4, 76, 93, 4, 4, 105.0f, 77.0f, 10.0f, 10.0f, 2.5f, 1.25f, 0.95f, 10
|
||||
4, 82, 60, 30, 94, 4, 4, 3, 2, 2, 105.0f, 77.0f, 10.0f, 1.4f, 1.2f, 0.95f
|
||||
}, {
|
||||
ASTCENC_PRE_VERYTHOROUGH,
|
||||
4, 256, 128, 64, 98, 4, 6, 12, 8, 3, 200.0f, 200.0f, 10.0f, 1.6f, 1.4f, 0.98f
|
||||
}, {
|
||||
ASTCENC_PRE_EXHAUSTIVE,
|
||||
4, 1024, 100, 4, 4, 200.0f, 200.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.99f, 0
|
||||
4, 256, 256, 256, 100, 4, 8, 32, 32, 32, 200.0f, 200.0f, 10.0f, 2.0f, 2.0f, 0.99f
|
||||
}
|
||||
}};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The static quality presets that are built-in for low bandwidth
|
||||
* presets (64 <= x texels per block).
|
||||
* @brief The static presets for low bandwidth encodings (64 <= x texels per block).
|
||||
*/
|
||||
static const std::array<astcenc_preset_config, 5> preset_configs_low {{
|
||||
static const std::array<astcenc_preset_config, 6> preset_configs_low {{
|
||||
{
|
||||
ASTCENC_PRE_FASTEST,
|
||||
2, 10, 40, 2, 2, 85.0f, 63.0f, 3.5f, 3.5f, 1.0f, 1.0f, 0.5f, 20
|
||||
2, 10, 6, 4, 40, 2, 2, 2, 2, 2, 85.0f, 63.0f, 3.5f, 1.0f, 1.0f, 0.80f
|
||||
}, {
|
||||
ASTCENC_PRE_FAST,
|
||||
2, 15, 55, 3, 3, 85.0f, 63.0f, 3.5f, 3.5f, 1.0f, 1.1f, 0.5f, 16
|
||||
2, 18, 12, 10, 55, 3, 3, 2, 2, 2, 85.0f, 63.0f, 3.5f, 1.0f, 1.0f, 0.85f
|
||||
}, {
|
||||
ASTCENC_PRE_MEDIUM,
|
||||
3, 30, 76, 3, 3, 95.0f, 70.0f, 3.5f, 3.5f, 1.2f, 1.25f, 0.65f, 12
|
||||
3, 34, 28, 16, 77, 3, 3, 2, 2, 2, 95.0f, 70.0f, 3.5f, 1.1f, 1.05f, 0.90f
|
||||
}, {
|
||||
ASTCENC_PRE_THOROUGH,
|
||||
4, 75, 92, 4, 4, 105.0f, 77.0f, 10.0f, 10.0f, 2.5f, 1.25f, 0.85f, 10
|
||||
4, 82, 60, 30, 93, 4, 4, 3, 2, 2, 105.0f, 77.0f, 10.0f, 1.3f, 1.2f, 0.97f
|
||||
}, {
|
||||
ASTCENC_PRE_VERYTHOROUGH,
|
||||
4, 256, 128, 64, 98, 4, 6, 9, 5, 2, 200.0f, 200.0f, 10.0f, 1.6f, 1.4f, 0.98f
|
||||
}, {
|
||||
ASTCENC_PRE_EXHAUSTIVE,
|
||||
4, 1024, 100, 4, 4, 200.0f, 200.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.99f, 0
|
||||
4, 256, 256, 256, 100, 4, 8, 32, 32, 32, 200.0f, 200.0f, 10.0f, 2.0f, 2.0f, 0.99f
|
||||
}
|
||||
}};
|
||||
|
||||
|
@ -266,8 +273,7 @@ static astcenc_error validate_flags(
|
|||
}
|
||||
|
||||
// Flags field must only contain at most a single map type
|
||||
exMask = ASTCENC_FLG_MAP_MASK
|
||||
| ASTCENC_FLG_MAP_NORMAL
|
||||
exMask = ASTCENC_FLG_MAP_NORMAL
|
||||
| ASTCENC_FLG_MAP_RGBM;
|
||||
if (popcount(flags & exMask) > 1)
|
||||
{
|
||||
|
@ -422,13 +428,17 @@ static astcenc_error validate_config(
|
|||
config.rgbm_m_scale = astc::max(config.rgbm_m_scale, 1.0f);
|
||||
|
||||
config.tune_partition_count_limit = astc::clamp(config.tune_partition_count_limit, 1u, 4u);
|
||||
config.tune_partition_index_limit = astc::clamp(config.tune_partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_2partition_index_limit = astc::clamp(config.tune_2partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_3partition_index_limit = astc::clamp(config.tune_3partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_4partition_index_limit = astc::clamp(config.tune_4partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_block_mode_limit = astc::clamp(config.tune_block_mode_limit, 1u, 100u);
|
||||
config.tune_refinement_limit = astc::max(config.tune_refinement_limit, 1u);
|
||||
config.tune_candidate_limit = astc::clamp(config.tune_candidate_limit, 1u, TUNE_MAX_TRIAL_CANDIDATES);
|
||||
config.tune_2partitioning_candidate_limit = astc::clamp(config.tune_2partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES);
|
||||
config.tune_3partitioning_candidate_limit = astc::clamp(config.tune_3partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES);
|
||||
config.tune_4partitioning_candidate_limit = astc::clamp(config.tune_4partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES);
|
||||
config.tune_db_limit = astc::max(config.tune_db_limit, 0.0f);
|
||||
config.tune_mode0_mse_overshoot = astc::max(config.tune_mode0_mse_overshoot, 1.0f);
|
||||
config.tune_refinement_mse_overshoot = astc::max(config.tune_refinement_mse_overshoot, 1.0f);
|
||||
config.tune_mse_overshoot = astc::max(config.tune_mse_overshoot, 1.0f);
|
||||
config.tune_2_partition_early_out_limit_factor = astc::max(config.tune_2_partition_early_out_limit_factor, 0.0f);
|
||||
config.tune_3_partition_early_out_limit_factor = astc::max(config.tune_3_partition_early_out_limit_factor, 0.0f);
|
||||
config.tune_2_plane_early_out_limit_correlation = astc::max(config.tune_2_plane_early_out_limit_correlation, 0.0f);
|
||||
|
@ -464,9 +474,23 @@ astcenc_error astcenc_config_init(
|
|||
astcenc_config* configp
|
||||
) {
|
||||
astcenc_error status;
|
||||
astcenc_config& config = *configp;
|
||||
|
||||
// Check basic library compatibility options here so they are checked early. Note, these checks
|
||||
// are repeated in context_alloc for cases where callers use a manually defined config struct
|
||||
status = validate_cpu_isa();
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = validate_cpu_float();
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Zero init all config fields; although most of will be over written
|
||||
astcenc_config& config = *configp;
|
||||
std::memset(&config, 0, sizeof(config));
|
||||
|
||||
// Process the block size
|
||||
|
@ -493,7 +517,7 @@ astcenc_error astcenc_config_init(
|
|||
return ASTCENC_ERR_BAD_QUALITY;
|
||||
}
|
||||
|
||||
static const std::array<astcenc_preset_config, 5>* preset_configs;
|
||||
static const std::array<astcenc_preset_config, 6>* preset_configs;
|
||||
int texels_int = block_x * block_y * block_z;
|
||||
if (texels_int < 25)
|
||||
{
|
||||
|
@ -525,21 +549,23 @@ astcenc_error astcenc_config_init(
|
|||
if (start == end)
|
||||
{
|
||||
config.tune_partition_count_limit = (*preset_configs)[start].tune_partition_count_limit;
|
||||
config.tune_partition_index_limit = (*preset_configs)[start].tune_partition_index_limit;
|
||||
config.tune_2partition_index_limit = (*preset_configs)[start].tune_2partition_index_limit;
|
||||
config.tune_3partition_index_limit = (*preset_configs)[start].tune_3partition_index_limit;
|
||||
config.tune_4partition_index_limit = (*preset_configs)[start].tune_4partition_index_limit;
|
||||
config.tune_block_mode_limit = (*preset_configs)[start].tune_block_mode_limit;
|
||||
config.tune_refinement_limit = (*preset_configs)[start].tune_refinement_limit;
|
||||
config.tune_candidate_limit = astc::min((*preset_configs)[start].tune_candidate_limit,
|
||||
TUNE_MAX_TRIAL_CANDIDATES);
|
||||
config.tune_candidate_limit = astc::min((*preset_configs)[start].tune_candidate_limit, TUNE_MAX_TRIAL_CANDIDATES);
|
||||
config.tune_2partitioning_candidate_limit = astc::min((*preset_configs)[start].tune_2partitioning_candidate_limit, TUNE_MAX_PARTITIONING_CANDIDATES);
|
||||
config.tune_3partitioning_candidate_limit = astc::min((*preset_configs)[start].tune_3partitioning_candidate_limit, TUNE_MAX_PARTITIONING_CANDIDATES);
|
||||
config.tune_4partitioning_candidate_limit = astc::min((*preset_configs)[start].tune_4partitioning_candidate_limit, TUNE_MAX_PARTITIONING_CANDIDATES);
|
||||
config.tune_db_limit = astc::max((*preset_configs)[start].tune_db_limit_a_base - 35 * ltexels,
|
||||
(*preset_configs)[start].tune_db_limit_b_base - 19 * ltexels);
|
||||
|
||||
config.tune_mode0_mse_overshoot = (*preset_configs)[start].tune_mode0_mse_overshoot;
|
||||
config.tune_refinement_mse_overshoot = (*preset_configs)[start].tune_refinement_mse_overshoot;
|
||||
config.tune_mse_overshoot = (*preset_configs)[start].tune_mse_overshoot;
|
||||
|
||||
config.tune_2_partition_early_out_limit_factor = (*preset_configs)[start].tune_2_partition_early_out_limit_factor;
|
||||
config.tune_3_partition_early_out_limit_factor =(*preset_configs)[start].tune_3_partition_early_out_limit_factor;
|
||||
config.tune_2_plane_early_out_limit_correlation = (*preset_configs)[start].tune_2_plane_early_out_limit_correlation;
|
||||
config.tune_low_weight_count_limit = (*preset_configs)[start].tune_low_weight_count_limit;
|
||||
}
|
||||
// Start and end node are not the same - so interpolate between them
|
||||
else
|
||||
|
@ -561,21 +587,27 @@ astcenc_error astcenc_config_init(
|
|||
#define LERPUI(param) static_cast<unsigned int>(LERPI(param))
|
||||
|
||||
config.tune_partition_count_limit = LERPI(tune_partition_count_limit);
|
||||
config.tune_partition_index_limit = LERPI(tune_partition_index_limit);
|
||||
config.tune_2partition_index_limit = LERPI(tune_2partition_index_limit);
|
||||
config.tune_3partition_index_limit = LERPI(tune_3partition_index_limit);
|
||||
config.tune_4partition_index_limit = LERPI(tune_4partition_index_limit);
|
||||
config.tune_block_mode_limit = LERPI(tune_block_mode_limit);
|
||||
config.tune_refinement_limit = LERPI(tune_refinement_limit);
|
||||
config.tune_candidate_limit = astc::min(LERPUI(tune_candidate_limit),
|
||||
TUNE_MAX_TRIAL_CANDIDATES);
|
||||
config.tune_2partitioning_candidate_limit = astc::min(LERPUI(tune_2partitioning_candidate_limit),
|
||||
BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_3partitioning_candidate_limit = astc::min(LERPUI(tune_3partitioning_candidate_limit),
|
||||
BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_4partitioning_candidate_limit = astc::min(LERPUI(tune_4partitioning_candidate_limit),
|
||||
BLOCK_MAX_PARTITIONINGS);
|
||||
config.tune_db_limit = astc::max(LERP(tune_db_limit_a_base) - 35 * ltexels,
|
||||
LERP(tune_db_limit_b_base) - 19 * ltexels);
|
||||
|
||||
config.tune_mode0_mse_overshoot = LERP(tune_mode0_mse_overshoot);
|
||||
config.tune_refinement_mse_overshoot = LERP(tune_refinement_mse_overshoot);
|
||||
config.tune_mse_overshoot = LERP(tune_mse_overshoot);
|
||||
|
||||
config.tune_2_partition_early_out_limit_factor = LERP(tune_2_partition_early_out_limit_factor);
|
||||
config.tune_3_partition_early_out_limit_factor = LERP(tune_3_partition_early_out_limit_factor);
|
||||
config.tune_2_plane_early_out_limit_correlation = LERP(tune_2_plane_early_out_limit_correlation);
|
||||
config.tune_low_weight_count_limit = LERPI(tune_low_weight_count_limit);
|
||||
#undef LERP
|
||||
#undef LERPI
|
||||
#undef LERPUI
|
||||
|
@ -632,12 +664,6 @@ astcenc_error astcenc_config_init(
|
|||
// so force compressor to try harder here ...
|
||||
config.tune_db_limit *= 1.03f;
|
||||
}
|
||||
else if (flags & ASTCENC_FLG_MAP_MASK)
|
||||
{
|
||||
// Masks are prone to blocking artifacts on mask edges
|
||||
// so force compressor to try harder here ...
|
||||
config.tune_db_limit *= 1.03f;
|
||||
}
|
||||
else if (flags & ASTCENC_FLG_MAP_RGBM)
|
||||
{
|
||||
config.rgbm_m_scale = 5.0f;
|
||||
|
@ -676,13 +702,13 @@ astcenc_error astcenc_context_alloc(
|
|||
astcenc_error status;
|
||||
const astcenc_config& config = *configp;
|
||||
|
||||
status = validate_cpu_float();
|
||||
status = validate_cpu_isa();
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = validate_cpu_isa();
|
||||
status = validate_cpu_float();
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
|
@ -714,7 +740,7 @@ astcenc_error astcenc_context_alloc(
|
|||
status = validate_config(ctx->config);
|
||||
if (status != ASTCENC_SUCCESS)
|
||||
{
|
||||
delete ctx;
|
||||
delete ctxo;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1316,7 +1342,6 @@ astcenc_error astcenc_get_block_info(
|
|||
|
||||
unpack_color_endpoints(ctx->config.profile,
|
||||
scb.color_formats[i],
|
||||
scb.get_color_quant_mode(),
|
||||
scb.color_values[i],
|
||||
rgb_hdr, a_hdr,
|
||||
endpnt[0], endpnt[1]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -46,6 +46,7 @@
|
|||
* lines for endpoint selection.
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/**
|
||||
|
@ -361,29 +362,27 @@ static void count_partition_mismatch_bits(
|
|||
unsigned int mismatch_counts[BLOCK_MAX_PARTITIONINGS]
|
||||
) {
|
||||
unsigned int active_count = bsd.partitioning_count_selected[partition_count - 1];
|
||||
promise(active_count > 0);
|
||||
|
||||
if (partition_count == 2)
|
||||
{
|
||||
for (unsigned int i = 0; i < active_count; i++)
|
||||
{
|
||||
int bitcount = partition_mismatch2(bitmaps, bsd.coverage_bitmaps_2[i]);
|
||||
mismatch_counts[i] = astc::max(bitcount, static_cast<int>(bsd.partitioning_valid_2[i]));
|
||||
mismatch_counts[i] = partition_mismatch2(bitmaps, bsd.coverage_bitmaps_2[i]);
|
||||
}
|
||||
}
|
||||
else if (partition_count == 3)
|
||||
{
|
||||
for (unsigned int i = 0; i < active_count; i++)
|
||||
{
|
||||
int bitcount = partition_mismatch3(bitmaps, bsd.coverage_bitmaps_3[i]);
|
||||
mismatch_counts[i] = astc::max(bitcount, static_cast<int>(bsd.partitioning_valid_3[i]));
|
||||
mismatch_counts[i] = partition_mismatch3(bitmaps, bsd.coverage_bitmaps_3[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < active_count; i++)
|
||||
{
|
||||
int bitcount = partition_mismatch4(bitmaps, bsd.coverage_bitmaps_4[i]);
|
||||
mismatch_counts[i] = astc::max(bitcount, static_cast<int>(bsd.partitioning_valid_4[i]));
|
||||
mismatch_counts[i] = partition_mismatch4(bitmaps, bsd.coverage_bitmaps_4[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,6 +401,7 @@ static unsigned int get_partition_ordering_by_mismatch_bits(
|
|||
const unsigned int mismatch_count[BLOCK_MAX_PARTITIONINGS],
|
||||
unsigned int partition_ordering[BLOCK_MAX_PARTITIONINGS]
|
||||
) {
|
||||
promise(partitioning_count > 0);
|
||||
unsigned int mscount[256] { 0 };
|
||||
|
||||
// Create the histogram of mismatch counts
|
||||
|
@ -487,13 +487,61 @@ static unsigned int compute_kmeans_partition_ordering(
|
|||
mismatch_counts, partition_ordering);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a partitioning into an order list of results, sorted by error.
|
||||
*
|
||||
* @param max_values The max number of entries in the best result arrays.
|
||||
* @param this_error The error of the new entry.
|
||||
* @param this_partition The partition ID of the new entry.
|
||||
* @param[out] best_errors The array of best error values.
|
||||
* @param[out] best_partitions The array of best partition values.
|
||||
*/
|
||||
static void insert_result(
|
||||
unsigned int max_values,
|
||||
float this_error,
|
||||
unsigned int this_partition,
|
||||
float* best_errors,
|
||||
unsigned int* best_partitions)
|
||||
{
|
||||
promise(max_values > 0);
|
||||
|
||||
// Don't bother searching if the current worst error beats the new error
|
||||
if (this_error >= best_errors[max_values - 1])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Else insert into the list in error-order
|
||||
for (unsigned int i = 0; i < max_values; i++)
|
||||
{
|
||||
// Existing result is better - move on ...
|
||||
if (this_error > best_errors[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Move existing results down one
|
||||
for (unsigned int j = max_values - 1; j > i; j--)
|
||||
{
|
||||
best_errors[j] = best_errors[j - 1];
|
||||
best_partitions[j] = best_partitions[j - 1];
|
||||
}
|
||||
|
||||
// Insert new result
|
||||
best_errors[i] = this_error;
|
||||
best_partitions[i] = this_partition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* See header for documentation. */
|
||||
void find_best_partition_candidates(
|
||||
unsigned int find_best_partition_candidates(
|
||||
const block_size_descriptor& bsd,
|
||||
const image_block& blk,
|
||||
unsigned int partition_count,
|
||||
unsigned int partition_search_limit,
|
||||
unsigned int best_partitions[2]
|
||||
unsigned int best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES],
|
||||
unsigned int requested_candidates
|
||||
) {
|
||||
// Constant used to estimate quantization error for a given partitioning; the optimal value for
|
||||
// this depends on bitrate. These values have been determined empirically.
|
||||
|
@ -520,17 +568,23 @@ void find_best_partition_candidates(
|
|||
unsigned int partition_sequence[BLOCK_MAX_PARTITIONINGS];
|
||||
unsigned int sequence_len = compute_kmeans_partition_ordering(bsd, blk, partition_count, partition_sequence);
|
||||
partition_search_limit = astc::min(partition_search_limit, sequence_len);
|
||||
requested_candidates = astc::min(partition_search_limit, requested_candidates);
|
||||
|
||||
bool uses_alpha = !blk.is_constant_channel(3);
|
||||
|
||||
// Partitioning errors assuming uncorrelated-chrominance endpoints
|
||||
float uncor_best_error { ERROR_CALC_DEFAULT };
|
||||
unsigned int uncor_best_partition { 0 };
|
||||
float uncor_best_errors[TUNE_MAX_PARTITIONING_CANDIDATES];
|
||||
unsigned int uncor_best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES];
|
||||
|
||||
// Partitioning errors assuming same-chrominance endpoints
|
||||
// Store two so we can always return one different to uncorr
|
||||
float samec_best_errors[2] { ERROR_CALC_DEFAULT, ERROR_CALC_DEFAULT };
|
||||
unsigned int samec_best_partitions[2] { 0, 0 };
|
||||
float samec_best_errors[TUNE_MAX_PARTITIONING_CANDIDATES];
|
||||
unsigned int samec_best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES];
|
||||
|
||||
for (unsigned int i = 0; i < requested_candidates; i++)
|
||||
{
|
||||
uncor_best_errors[i] = ERROR_CALC_DEFAULT;
|
||||
samec_best_errors[i] = ERROR_CALC_DEFAULT;
|
||||
}
|
||||
|
||||
if (uses_alpha)
|
||||
{
|
||||
|
@ -604,25 +658,8 @@ void find_best_partition_candidates(
|
|||
samec_error += dot_s(samec_vector * samec_vector, error_weights);
|
||||
}
|
||||
|
||||
if (uncor_error < uncor_best_error)
|
||||
{
|
||||
uncor_best_error = uncor_error;
|
||||
uncor_best_partition = partition;
|
||||
}
|
||||
|
||||
if (samec_error < samec_best_errors[0])
|
||||
{
|
||||
samec_best_errors[1] = samec_best_errors[0];
|
||||
samec_best_partitions[1] = samec_best_partitions[0];
|
||||
|
||||
samec_best_errors[0] = samec_error;
|
||||
samec_best_partitions[0] = partition;
|
||||
}
|
||||
else if (samec_error < samec_best_errors[1])
|
||||
{
|
||||
samec_best_errors[1] = samec_error;
|
||||
samec_best_partitions[1] = partition;
|
||||
}
|
||||
insert_result(requested_candidates, uncor_error, partition, uncor_best_errors, uncor_best_partitions);
|
||||
insert_result(requested_candidates, samec_error, partition, samec_best_errors, samec_best_partitions);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -644,10 +681,10 @@ void find_best_partition_candidates(
|
|||
partition_lines3& pl = plines[j];
|
||||
|
||||
pl.uncor_line.a = pm.avg;
|
||||
pl.uncor_line.b = normalize_safe(pm.dir.swz<0, 1, 2>(), unit3());
|
||||
pl.uncor_line.b = normalize_safe(pm.dir, unit3());
|
||||
|
||||
pl.samec_line.a = vfloat4::zero();
|
||||
pl.samec_line.b = normalize_safe(pm.avg.swz<0, 1, 2>(), unit3());
|
||||
pl.samec_line.b = normalize_safe(pm.avg, unit3());
|
||||
|
||||
pl.uncor_pline.amod = pl.uncor_line.a - pl.uncor_line.b * dot3(pl.uncor_line.a, pl.uncor_line.b);
|
||||
pl.uncor_pline.bs = pl.uncor_line.b;
|
||||
|
@ -689,50 +726,55 @@ void find_best_partition_candidates(
|
|||
samec_error += dot3_s(samec_vector * samec_vector, error_weights);
|
||||
}
|
||||
|
||||
if (uncor_error < uncor_best_error)
|
||||
{
|
||||
uncor_best_error = uncor_error;
|
||||
uncor_best_partition = partition;
|
||||
}
|
||||
insert_result(requested_candidates, uncor_error, partition, uncor_best_errors, uncor_best_partitions);
|
||||
insert_result(requested_candidates, samec_error, partition, samec_best_errors, samec_best_partitions);
|
||||
}
|
||||
}
|
||||
|
||||
if (samec_error < samec_best_errors[0])
|
||||
{
|
||||
samec_best_errors[1] = samec_best_errors[0];
|
||||
samec_best_partitions[1] = samec_best_partitions[0];
|
||||
bool best_is_uncor = uncor_best_partitions[0] > samec_best_partitions[0];
|
||||
|
||||
samec_best_errors[0] = samec_error;
|
||||
samec_best_partitions[0] = partition;
|
||||
}
|
||||
else if (samec_error < samec_best_errors[1])
|
||||
unsigned int interleave[2 * TUNE_MAX_PARTITIONING_CANDIDATES];
|
||||
for (unsigned int i = 0; i < requested_candidates; i++)
|
||||
{
|
||||
if (best_is_uncor)
|
||||
{
|
||||
interleave[2 * i] = bsd.get_raw_partition_info(partition_count, uncor_best_partitions[i]).partition_index;
|
||||
interleave[2 * i + 1] = bsd.get_raw_partition_info(partition_count, samec_best_partitions[i]).partition_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
interleave[2 * i] = bsd.get_raw_partition_info(partition_count, samec_best_partitions[i]).partition_index;
|
||||
interleave[2 * i + 1] = bsd.get_raw_partition_info(partition_count, uncor_best_partitions[i]).partition_index;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t bitmasks[1024/64] { 0 };
|
||||
unsigned int emitted = 0;
|
||||
|
||||
// Deduplicate the first "requested" entries
|
||||
for (unsigned int i = 0; i < requested_candidates * 2; i++)
|
||||
{
|
||||
unsigned int partition = interleave[i];
|
||||
|
||||
unsigned int word = partition / 64;
|
||||
unsigned int bit = partition % 64;
|
||||
|
||||
bool written = bitmasks[word] & (1ull << bit);
|
||||
|
||||
if (!written)
|
||||
{
|
||||
best_partitions[emitted] = partition;
|
||||
bitmasks[word] |= 1ull << bit;
|
||||
emitted++;
|
||||
|
||||
if (emitted == requested_candidates)
|
||||
{
|
||||
samec_best_errors[1] = samec_error;
|
||||
samec_best_partitions[1] = partition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same partition is best for both, so use this first unconditionally
|
||||
if (uncor_best_partition == samec_best_partitions[0])
|
||||
{
|
||||
best_partitions[0] = samec_best_partitions[0];
|
||||
best_partitions[1] = samec_best_partitions[1];
|
||||
}
|
||||
// Uncor is best
|
||||
else if (uncor_best_error <= samec_best_errors[0])
|
||||
{
|
||||
best_partitions[0] = uncor_best_partition;
|
||||
best_partitions[1] = samec_best_partitions[0];
|
||||
}
|
||||
// Samec is best
|
||||
else
|
||||
{
|
||||
best_partitions[0] = samec_best_partitions[0];
|
||||
best_partitions[1] = uncor_best_partition;
|
||||
}
|
||||
|
||||
// Convert these back into canonical partition IDs for the rest of the codec
|
||||
best_partitions[0] = bsd.get_raw_partition_info(partition_count, best_partitions[0]).partition_index;
|
||||
best_partitions[1] = bsd.get_raw_partition_info(partition_count, best_partitions[1]).partition_index;
|
||||
return emitted;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -41,10 +41,10 @@ static vfloat bilinear_infill_vla(
|
|||
unsigned int index
|
||||
) {
|
||||
// Load the bilinear filter texel weight indexes in the decimated grid
|
||||
vint weight_idx0 = vint(di.texel_weights_4t[0] + index);
|
||||
vint weight_idx1 = vint(di.texel_weights_4t[1] + index);
|
||||
vint weight_idx2 = vint(di.texel_weights_4t[2] + index);
|
||||
vint weight_idx3 = vint(di.texel_weights_4t[3] + index);
|
||||
vint weight_idx0 = vint(di.texel_weights_tr[0] + index);
|
||||
vint weight_idx1 = vint(di.texel_weights_tr[1] + index);
|
||||
vint weight_idx2 = vint(di.texel_weights_tr[2] + index);
|
||||
vint weight_idx3 = vint(di.texel_weights_tr[3] + index);
|
||||
|
||||
// Load the bilinear filter weights from the decimated grid
|
||||
vfloat weight_val0 = gatherf(weights, weight_idx0);
|
||||
|
@ -53,10 +53,10 @@ static vfloat bilinear_infill_vla(
|
|||
vfloat weight_val3 = gatherf(weights, weight_idx3);
|
||||
|
||||
// Load the weight contribution factors for each decimated weight
|
||||
vfloat tex_weight_float0 = loada(di.texel_weights_float_4t[0] + index);
|
||||
vfloat tex_weight_float1 = loada(di.texel_weights_float_4t[1] + index);
|
||||
vfloat tex_weight_float2 = loada(di.texel_weights_float_4t[2] + index);
|
||||
vfloat tex_weight_float3 = loada(di.texel_weights_float_4t[3] + index);
|
||||
vfloat tex_weight_float0 = loada(di.texel_weight_contribs_float_tr[0] + index);
|
||||
vfloat tex_weight_float1 = loada(di.texel_weight_contribs_float_tr[1] + index);
|
||||
vfloat tex_weight_float2 = loada(di.texel_weight_contribs_float_tr[2] + index);
|
||||
vfloat tex_weight_float3 = loada(di.texel_weight_contribs_float_tr[3] + index);
|
||||
|
||||
// Compute the bilinear interpolation to generate the per-texel weight
|
||||
return (weight_val0 * tex_weight_float0 + weight_val1 * tex_weight_float1) +
|
||||
|
@ -81,16 +81,16 @@ static vfloat bilinear_infill_vla_2(
|
|||
unsigned int index
|
||||
) {
|
||||
// Load the bilinear filter texel weight indexes in the decimated grid
|
||||
vint weight_idx0 = vint(di.texel_weights_4t[0] + index);
|
||||
vint weight_idx1 = vint(di.texel_weights_4t[1] + index);
|
||||
vint weight_idx0 = vint(di.texel_weights_tr[0] + index);
|
||||
vint weight_idx1 = vint(di.texel_weights_tr[1] + index);
|
||||
|
||||
// Load the bilinear filter weights from the decimated grid
|
||||
vfloat weight_val0 = gatherf(weights, weight_idx0);
|
||||
vfloat weight_val1 = gatherf(weights, weight_idx1);
|
||||
|
||||
// Load the weight contribution factors for each decimated weight
|
||||
vfloat tex_weight_float0 = loada(di.texel_weights_float_4t[0] + index);
|
||||
vfloat tex_weight_float1 = loada(di.texel_weights_float_4t[1] + index);
|
||||
vfloat tex_weight_float0 = loada(di.texel_weight_contribs_float_tr[0] + index);
|
||||
vfloat tex_weight_float1 = loada(di.texel_weight_contribs_float_tr[1] + index);
|
||||
|
||||
// Compute the bilinear interpolation to generate the per-texel weight
|
||||
return (weight_val0 * tex_weight_float0 + weight_val1 * tex_weight_float1);
|
||||
|
@ -268,13 +268,13 @@ static void compute_ideal_colors_and_weights_2_comp(
|
|||
|
||||
for (unsigned int i = 0; i < partition_count; i++)
|
||||
{
|
||||
vfloat4 dir = pms[i].dir.swz<0, 1>();
|
||||
vfloat4 dir = pms[i].dir;
|
||||
if (hadd_s(dir) < 0.0f)
|
||||
{
|
||||
dir = vfloat4::zero() - dir;
|
||||
}
|
||||
|
||||
line2 line { pms[i].avg.swz<0, 1>(), normalize_safe(dir, unit2()) };
|
||||
line2 line { pms[i].avg, normalize_safe(dir, unit2()) };
|
||||
float lowparam { 1e10f };
|
||||
float highparam { -1e10f };
|
||||
|
||||
|
@ -691,8 +691,8 @@ float compute_error_of_weight_set_1plane(
|
|||
const float* dec_weight_quant_uvalue
|
||||
) {
|
||||
vfloatacc error_summav = vfloatacc::zero();
|
||||
float error_summa = 0.0f;
|
||||
unsigned int texel_count = di.texel_count;
|
||||
promise(texel_count > 0);
|
||||
|
||||
// Process SIMD-width chunks, safe to over-fetch - the extra space is zero initialized
|
||||
if (di.max_texel_weight_count > 2)
|
||||
|
@ -745,7 +745,7 @@ float compute_error_of_weight_set_1plane(
|
|||
}
|
||||
|
||||
// Resolve the final scalar accumulator sum
|
||||
return error_summa = hadd_s(error_summav);
|
||||
return hadd_s(error_summav);
|
||||
}
|
||||
|
||||
/* See header for documentation. */
|
||||
|
@ -758,6 +758,7 @@ float compute_error_of_weight_set_2planes(
|
|||
) {
|
||||
vfloatacc error_summav = vfloatacc::zero();
|
||||
unsigned int texel_count = di.texel_count;
|
||||
promise(texel_count > 0);
|
||||
|
||||
// Process SIMD-width chunks, safe to over-fetch - the extra space is zero initialized
|
||||
if (di.max_texel_weight_count > 2)
|
||||
|
@ -862,8 +863,7 @@ void compute_ideal_weights_for_decimation(
|
|||
// zero-initialized SIMD over-fetch region
|
||||
if (is_direct)
|
||||
{
|
||||
unsigned int texel_count_simd = round_up_to_simd_multiple_vla(texel_count);
|
||||
for (unsigned int i = 0; i < texel_count_simd; i += ASTCENC_SIMD_WIDTH)
|
||||
for (unsigned int i = 0; i < texel_count; i += ASTCENC_SIMD_WIDTH)
|
||||
{
|
||||
vfloat weight(ei.weights + i);
|
||||
storea(weight, dec_weight_ideal_value + i);
|
||||
|
@ -894,8 +894,8 @@ void compute_ideal_weights_for_decimation(
|
|||
|
||||
for (unsigned int j = 0; j < max_texel_count; j++)
|
||||
{
|
||||
vint texel(di.weight_texel[j] + i);
|
||||
vfloat weight = loada(di.weights_flt[j] + i);
|
||||
vint texel(di.weight_texels_tr[j] + i);
|
||||
vfloat weight = loada(di.weights_texel_contribs_tr[j] + i);
|
||||
|
||||
if (!constant_wes)
|
||||
{
|
||||
|
@ -952,8 +952,8 @@ void compute_ideal_weights_for_decimation(
|
|||
|
||||
for (unsigned int j = 0; j < max_texel_count; j++)
|
||||
{
|
||||
vint texel(di.weight_texel[j] + i);
|
||||
vfloat contrib_weight = loada(di.weights_flt[j] + i);
|
||||
vint texel(di.weight_texels_tr[j] + i);
|
||||
vfloat contrib_weight = loada(di.weights_texel_contribs_tr[j] + i);
|
||||
|
||||
if (!constant_wes)
|
||||
{
|
||||
|
@ -971,7 +971,7 @@ void compute_ideal_weights_for_decimation(
|
|||
vfloat step = (error_change1 * chd_scale) / error_change0;
|
||||
step = clamp(-stepsize, stepsize, step);
|
||||
|
||||
// Update the weight; note this can store negative values.
|
||||
// Update the weight; note this can store negative values
|
||||
storea(weight_val + step, dec_weight_ideal_value + i);
|
||||
}
|
||||
}
|
||||
|
@ -1216,7 +1216,7 @@ void recompute_ideal_colors_1plane(
|
|||
// Only compute a partition mean if more than one partition
|
||||
if (partition_count > 1)
|
||||
{
|
||||
rgba_sum = vfloat4(1e-17f);
|
||||
rgba_sum = vfloat4::zero();
|
||||
promise(texel_count > 0);
|
||||
for (unsigned int j = 0; j < texel_count; j++)
|
||||
{
|
||||
|
@ -1252,7 +1252,6 @@ void recompute_ideal_colors_1plane(
|
|||
for (unsigned int j = 0; j < texel_count; j++)
|
||||
{
|
||||
unsigned int tix = texel_indexes[j];
|
||||
|
||||
vfloat4 rgba = blk.texel(tix);
|
||||
|
||||
float idx0 = undec_weight_ref[tix];
|
||||
|
@ -1285,14 +1284,11 @@ void recompute_ideal_colors_1plane(
|
|||
vfloat4 right_sum = vfloat4(right_sum_s) * color_weight;
|
||||
vfloat4 lmrs_sum = vfloat3(left_sum_s, middle_sum_s, right_sum_s) * ls_weight;
|
||||
|
||||
vfloat4 weight_weight_sum = vfloat4(weight_weight_sum_s) * color_weight;
|
||||
float psum = right_sum_s * hadd_rgb_s(color_weight);
|
||||
|
||||
color_vec_x = color_vec_x * color_weight;
|
||||
color_vec_y = color_vec_y * color_weight;
|
||||
|
||||
// Initialize the luminance and scale vectors with a reasonable default
|
||||
float scalediv = scale_min * (1.0f / astc::max(scale_max, 1e-10f));
|
||||
float scalediv = scale_min / astc::max(scale_max, 1e-10f);
|
||||
scalediv = astc::clamp1f(scalediv);
|
||||
|
||||
vfloat4 sds = scale_dir * scale_max;
|
||||
|
@ -1344,32 +1340,38 @@ void recompute_ideal_colors_1plane(
|
|||
|
||||
if (fabsf(ls_det1) > (ls_mss1 * 1e-4f) && scale_ep0 == scale_ep0 && scale_ep1 == scale_ep1 && scale_ep0 < scale_ep1)
|
||||
{
|
||||
float scalediv2 = scale_ep0 * (1.0f / scale_ep1);
|
||||
float scalediv2 = scale_ep0 / scale_ep1;
|
||||
vfloat4 sdsm = scale_dir * scale_ep1;
|
||||
rgbs_vectors[i] = vfloat4(sdsm.lane<0>(), sdsm.lane<1>(), sdsm.lane<2>(), scalediv2);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculations specific to mode #7, the HDR RGB-scale mode
|
||||
vfloat4 rgbq_sum = color_vec_x + color_vec_y;
|
||||
rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y));
|
||||
|
||||
vfloat4 rgbovec = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum);
|
||||
rgbo_vectors[i] = rgbovec;
|
||||
|
||||
// We can get a failure due to the use of a singular (non-invertible) matrix
|
||||
// If it failed, compute rgbo_vectors[] with a different method ...
|
||||
if (astc::isnan(dot_s(rgbovec, rgbovec)))
|
||||
// Calculations specific to mode #7, the HDR RGB-scale mode - skip if known LDR
|
||||
if (blk.rgb_lns[0] || blk.alpha_lns[0])
|
||||
{
|
||||
vfloat4 v0 = ep.endpt0[i];
|
||||
vfloat4 v1 = ep.endpt1[i];
|
||||
vfloat4 weight_weight_sum = vfloat4(weight_weight_sum_s) * color_weight;
|
||||
float psum = right_sum_s * hadd_rgb_s(color_weight);
|
||||
|
||||
float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f);
|
||||
avgdif = astc::max(avgdif, 0.0f);
|
||||
vfloat4 rgbq_sum = color_vec_x + color_vec_y;
|
||||
rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y));
|
||||
|
||||
vfloat4 avg = (v0 + v1) * 0.5f;
|
||||
vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f;
|
||||
rgbo_vectors[i] = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif);
|
||||
vfloat4 rgbovec = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum);
|
||||
rgbo_vectors[i] = rgbovec;
|
||||
|
||||
// We can get a failure due to the use of a singular (non-invertible) matrix
|
||||
// If it failed, compute rgbo_vectors[] with a different method ...
|
||||
if (astc::isnan(dot_s(rgbovec, rgbovec)))
|
||||
{
|
||||
vfloat4 v0 = ep.endpt0[i];
|
||||
vfloat4 v1 = ep.endpt1[i];
|
||||
|
||||
float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f);
|
||||
avgdif = astc::max(avgdif, 0.0f);
|
||||
|
||||
vfloat4 avg = (v0 + v1) * 0.5f;
|
||||
vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f;
|
||||
rgbo_vectors[i] = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1517,7 +1519,7 @@ void recompute_ideal_colors_2planes(
|
|||
color_vec_x += cwprod - cwiprod;
|
||||
|
||||
scale_vec += vfloat2(om_idx0, idx0) * (ls_weight * scale);
|
||||
weight_weight_sum += (color_weight * color_idx);
|
||||
weight_weight_sum += color_idx;
|
||||
}
|
||||
|
||||
vfloat4 left1_sum = vfloat4(left1_sum_s) * color_weight;
|
||||
|
@ -1529,13 +1531,11 @@ void recompute_ideal_colors_2planes(
|
|||
vfloat4 middle2_sum = vfloat4(middle2_sum_s) * color_weight;
|
||||
vfloat4 right2_sum = vfloat4(right2_sum_s) * color_weight;
|
||||
|
||||
float psum = dot3_s(select(right1_sum, right2_sum, p2_mask), color_weight);
|
||||
|
||||
color_vec_x = color_vec_x * color_weight;
|
||||
color_vec_y = color_vec_y * color_weight;
|
||||
|
||||
// Initialize the luminance and scale vectors with a reasonable default
|
||||
float scalediv = scale_min * (1.0f / astc::max(scale_max, 1e-10f));
|
||||
float scalediv = scale_min / astc::max(scale_max, 1e-10f);
|
||||
scalediv = astc::clamp1f(scalediv);
|
||||
|
||||
vfloat4 sds = scale_dir * scale_max;
|
||||
|
@ -1591,7 +1591,7 @@ void recompute_ideal_colors_2planes(
|
|||
|
||||
if (fabsf(ls_det1) > (ls_mss1 * 1e-4f) && scale_ep0 == scale_ep0 && scale_ep1 == scale_ep1 && scale_ep0 < scale_ep1)
|
||||
{
|
||||
float scalediv2 = scale_ep0 * (1.0f / scale_ep1);
|
||||
float scalediv2 = scale_ep0 / scale_ep1;
|
||||
vfloat4 sdsm = scale_dir * scale_ep1;
|
||||
rgbs_vector = vfloat4(sdsm.lane<0>(), sdsm.lane<1>(), sdsm.lane<2>(), scalediv2);
|
||||
}
|
||||
|
@ -1631,26 +1631,32 @@ void recompute_ideal_colors_2planes(
|
|||
ep.endpt1[0] = select(ep.endpt1[0], ep1, full_mask);
|
||||
}
|
||||
|
||||
// Calculations specific to mode #7, the HDR RGB-scale mode
|
||||
vfloat4 rgbq_sum = color_vec_x + color_vec_y;
|
||||
rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y));
|
||||
|
||||
rgbo_vector = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum);
|
||||
|
||||
// We can get a failure due to the use of a singular (non-invertible) matrix
|
||||
// If it failed, compute rgbo_vectors[] with a different method ...
|
||||
if (astc::isnan(dot_s(rgbo_vector, rgbo_vector)))
|
||||
// Calculations specific to mode #7, the HDR RGB-scale mode - skip if known LDR
|
||||
if (blk.rgb_lns[0] || blk.alpha_lns[0])
|
||||
{
|
||||
vfloat4 v0 = ep.endpt0[0];
|
||||
vfloat4 v1 = ep.endpt1[0];
|
||||
weight_weight_sum = weight_weight_sum * color_weight;
|
||||
float psum = dot3_s(select(right1_sum, right2_sum, p2_mask), color_weight);
|
||||
|
||||
float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f);
|
||||
avgdif = astc::max(avgdif, 0.0f);
|
||||
vfloat4 rgbq_sum = color_vec_x + color_vec_y;
|
||||
rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y));
|
||||
|
||||
vfloat4 avg = (v0 + v1) * 0.5f;
|
||||
vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f;
|
||||
rgbo_vector = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum);
|
||||
|
||||
rgbo_vector = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif);
|
||||
// We can get a failure due to the use of a singular (non-invertible) matrix
|
||||
// If it failed, compute rgbo_vectors[] with a different method ...
|
||||
if (astc::isnan(dot_s(rgbo_vector, rgbo_vector)))
|
||||
{
|
||||
vfloat4 v0 = ep.endpt0[0];
|
||||
vfloat4 v1 = ep.endpt1[0];
|
||||
|
||||
float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f);
|
||||
avgdif = astc::max(avgdif, 0.0f);
|
||||
|
||||
vfloat4 avg = (v0 + v1) * 0.5f;
|
||||
vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f;
|
||||
|
||||
rgbo_vector = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <array>
|
||||
|
||||
/** @brief Unpacked quint triplets <low,middle,high> for each packed value */
|
||||
// TODO: Bitpack these into a uint16_t?
|
||||
static const uint8_t quints_of_integer[128][3] {
|
||||
{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0},
|
||||
{4, 0, 0}, {0, 4, 0}, {4, 4, 0}, {4, 4, 4},
|
||||
|
@ -99,6 +100,7 @@ static const uint8_t integer_of_quints[5][5][5] {
|
|||
};
|
||||
|
||||
/** @brief Unpacked trit quintuplets <low,...,high> for each packed value */
|
||||
// TODO: Bitpack these into a uint16_t?
|
||||
static const uint8_t trits_of_integer[256][5] {
|
||||
{0, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, {2, 0, 0, 0, 0}, {0, 0, 2, 0, 0},
|
||||
{0, 1, 0, 0, 0}, {1, 1, 0, 0, 0}, {2, 1, 0, 0, 0}, {1, 0, 2, 0, 0},
|
||||
|
@ -334,44 +336,41 @@ static const uint8_t integer_of_trits[3][3][3][3][3] {
|
|||
*/
|
||||
struct btq_count
|
||||
{
|
||||
/** @brief The quantization level. */
|
||||
uint8_t quant;
|
||||
|
||||
/** @brief The number of bits. */
|
||||
uint8_t bits;
|
||||
uint8_t bits:6;
|
||||
|
||||
/** @brief The number of trits. */
|
||||
uint8_t trits;
|
||||
uint8_t trits:1;
|
||||
|
||||
/** @brief The number of quints. */
|
||||
uint8_t quints;
|
||||
uint8_t quints:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The table of bits, trits, and quints needed for a quant encode.
|
||||
*/
|
||||
static const std::array<btq_count, 21> btq_counts {{
|
||||
{ QUANT_2, 1, 0, 0 },
|
||||
{ QUANT_3, 0, 1, 0 },
|
||||
{ QUANT_4, 2, 0, 0 },
|
||||
{ QUANT_5, 0, 0, 1 },
|
||||
{ QUANT_6, 1, 1, 0 },
|
||||
{ QUANT_8, 3, 0, 0 },
|
||||
{ QUANT_10, 1, 0, 1 },
|
||||
{ QUANT_12, 2, 1, 0 },
|
||||
{ QUANT_16, 4, 0, 0 },
|
||||
{ QUANT_20, 2, 0, 1 },
|
||||
{ QUANT_24, 3, 1, 0 },
|
||||
{ QUANT_32, 5, 0, 0 },
|
||||
{ QUANT_40, 3, 0, 1 },
|
||||
{ QUANT_48, 4, 1, 0 },
|
||||
{ QUANT_64, 6, 0, 0 },
|
||||
{ QUANT_80, 4, 0, 1 },
|
||||
{ QUANT_96, 5, 1, 0 },
|
||||
{ QUANT_128, 7, 0, 0 },
|
||||
{ QUANT_160, 5, 0, 1 },
|
||||
{ QUANT_192, 6, 1, 0 },
|
||||
{ QUANT_256, 8, 0, 0 }
|
||||
{ 1, 0, 0 }, // QUANT_2
|
||||
{ 0, 1, 0 }, // QUANT_3
|
||||
{ 2, 0, 0 }, // QUANT_4
|
||||
{ 0, 0, 1 }, // QUANT_5
|
||||
{ 1, 1, 0 }, // QUANT_6
|
||||
{ 3, 0, 0 }, // QUANT_8
|
||||
{ 1, 0, 1 }, // QUANT_10
|
||||
{ 2, 1, 0 }, // QUANT_12
|
||||
{ 4, 0, 0 }, // QUANT_16
|
||||
{ 2, 0, 1 }, // QUANT_20
|
||||
{ 3, 1, 0 }, // QUANT_24
|
||||
{ 5, 0, 0 }, // QUANT_32
|
||||
{ 3, 0, 1 }, // QUANT_40
|
||||
{ 4, 1, 0 }, // QUANT_48
|
||||
{ 6, 0, 0 }, // QUANT_64
|
||||
{ 4, 0, 1 }, // QUANT_80
|
||||
{ 5, 1, 0 }, // QUANT_96
|
||||
{ 7, 0, 0 }, // QUANT_128
|
||||
{ 5, 0, 1 }, // QUANT_160
|
||||
{ 6, 1, 0 }, // QUANT_192
|
||||
{ 8, 0, 0 } // QUANT_256
|
||||
}};
|
||||
|
||||
/**
|
||||
|
@ -382,44 +381,38 @@ static const std::array<btq_count, 21> btq_counts {{
|
|||
*/
|
||||
struct ise_size
|
||||
{
|
||||
/** @brief The quantization level. */
|
||||
uint8_t quant;
|
||||
|
||||
/** @brief The scaling parameter. */
|
||||
uint8_t scale;
|
||||
|
||||
/** @brief The rounding parameter. */
|
||||
uint8_t round;
|
||||
uint8_t scale:6;
|
||||
|
||||
/** @brief The divisor parameter. */
|
||||
uint8_t divisor;
|
||||
uint8_t divisor:2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The table of scale, round, and divisors needed for quant sizing.
|
||||
*/
|
||||
static const std::array<ise_size, 21> ise_sizes {{
|
||||
{ QUANT_2, 1, 0, 1 },
|
||||
{ QUANT_3, 8, 4, 5 },
|
||||
{ QUANT_4, 2, 0, 1 },
|
||||
{ QUANT_5, 7, 2, 3 },
|
||||
{ QUANT_6, 13, 4, 5 },
|
||||
{ QUANT_8, 3, 0, 1 },
|
||||
{ QUANT_10, 10, 2, 3 },
|
||||
{ QUANT_12, 18, 4, 5 },
|
||||
{ QUANT_16, 4, 0, 1 },
|
||||
{ QUANT_20, 13, 2, 3 },
|
||||
{ QUANT_24, 23, 4, 5 },
|
||||
{ QUANT_32, 5, 0, 1 },
|
||||
{ QUANT_40, 16, 2, 3 },
|
||||
{ QUANT_48, 28, 4, 5 },
|
||||
{ QUANT_64, 6, 0, 1 },
|
||||
{ QUANT_80, 19, 2, 3 },
|
||||
{ QUANT_96, 33, 4, 5 },
|
||||
{ QUANT_128, 7, 0, 1 },
|
||||
{ QUANT_160, 22, 2, 3 },
|
||||
{ QUANT_192, 38, 4, 5 },
|
||||
{ QUANT_256, 8, 0, 1 }
|
||||
{ 1, 0 }, // QUANT_2
|
||||
{ 8, 2 }, // QUANT_3
|
||||
{ 2, 0 }, // QUANT_4
|
||||
{ 7, 1 }, // QUANT_5
|
||||
{ 13, 2 }, // QUANT_6
|
||||
{ 3, 0 }, // QUANT_8
|
||||
{ 10, 1 }, // QUANT_10
|
||||
{ 18, 2 }, // QUANT_12
|
||||
{ 4, 0 }, // QUANT_16
|
||||
{ 13, 1 }, // QUANT_20
|
||||
{ 23, 2 }, // QUANT_24
|
||||
{ 5, 0 }, // QUANT_32
|
||||
{ 16, 1 }, // QUANT_40
|
||||
{ 28, 2 }, // QUANT_48
|
||||
{ 6, 0 }, // QUANT_64
|
||||
{ 19, 1 }, // QUANT_80
|
||||
{ 33, 2 }, // QUANT_96
|
||||
{ 7, 0 }, // QUANT_128
|
||||
{ 22, 1 }, // QUANT_160
|
||||
{ 38, 2 }, // QUANT_192
|
||||
{ 8, 0 } // QUANT_256
|
||||
}};
|
||||
|
||||
/* See header for documentation. */
|
||||
|
@ -435,7 +428,8 @@ unsigned int get_ise_sequence_bitcount(
|
|||
}
|
||||
|
||||
auto& entry = ise_sizes[quant_level];
|
||||
return (entry.scale * character_count + entry.round) / entry.divisor;
|
||||
unsigned int divisor = (entry.divisor << 1) + 1;
|
||||
return (entry.scale * character_count + divisor - 1) / divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -645,7 +639,6 @@ void encode_ise(
|
|||
// Write out just bits
|
||||
else
|
||||
{
|
||||
promise(character_count > 0);
|
||||
for (unsigned int i = 0; i < character_count; i++)
|
||||
{
|
||||
write_bits(input_data[i], bits, bit_offset, output_data);
|
||||
|
@ -685,10 +678,10 @@ void decode_ise(
|
|||
|
||||
if (trits)
|
||||
{
|
||||
static const unsigned int bits_to_read[5] { 2, 2, 1, 2, 1 };
|
||||
static const unsigned int block_shift[5] { 0, 2, 4, 5, 7 };
|
||||
static const unsigned int next_lcounter[5] { 1, 2, 3, 4, 0 };
|
||||
static const unsigned int hcounter_incr[5] { 0, 0, 0, 0, 1 };
|
||||
static const uint8_t bits_to_read[5] { 2, 2, 1, 2, 1 };
|
||||
static const uint8_t block_shift[5] { 0, 2, 4, 5, 7 };
|
||||
static const uint8_t next_lcounter[5] { 1, 2, 3, 4, 0 };
|
||||
static const uint8_t hcounter_incr[5] { 0, 0, 0, 0, 1 };
|
||||
unsigned int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data);
|
||||
bit_offset += bits_to_read[lcounter];
|
||||
tq_blocks[hcounter] |= tdata << block_shift[lcounter];
|
||||
|
@ -698,10 +691,10 @@ void decode_ise(
|
|||
|
||||
if (quints)
|
||||
{
|
||||
static const unsigned int bits_to_read[3] { 3, 2, 2 };
|
||||
static const unsigned int block_shift[3] { 0, 3, 5 };
|
||||
static const unsigned int next_lcounter[3] { 1, 2, 0 };
|
||||
static const unsigned int hcounter_incr[3] { 0, 0, 1 };
|
||||
static const uint8_t bits_to_read[3] { 3, 2, 2 };
|
||||
static const uint8_t block_shift[3] { 0, 3, 5 };
|
||||
static const uint8_t next_lcounter[3] { 1, 2, 0 };
|
||||
static const uint8_t hcounter_incr[3] { 0, 0, 1 };
|
||||
unsigned int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data);
|
||||
bit_offset += bits_to_read[lcounter];
|
||||
tq_blocks[hcounter] |= tdata << block_shift[lcounter];
|
||||
|
@ -714,6 +707,7 @@ void decode_ise(
|
|||
if (trits)
|
||||
{
|
||||
unsigned int trit_blocks = (character_count + 4) / 5;
|
||||
promise(trit_blocks > 0);
|
||||
for (unsigned int i = 0; i < trit_blocks; i++)
|
||||
{
|
||||
const uint8_t *tritptr = trits_of_integer[tq_blocks[i]];
|
||||
|
@ -728,6 +722,7 @@ void decode_ise(
|
|||
if (quints)
|
||||
{
|
||||
unsigned int quint_blocks = (character_count + 2) / 3;
|
||||
promise(quint_blocks > 0);
|
||||
for (unsigned int i = 0; i < quint_blocks; i++)
|
||||
{
|
||||
const uint8_t *quintptr = quints_of_integer[tq_blocks[i]];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -130,7 +130,14 @@ static constexpr unsigned int TUNE_MIN_TEXELS_MODE0_FASTPATH { 24 };
|
|||
*
|
||||
* This can be dynamically reduced by the compression quality preset.
|
||||
*/
|
||||
static constexpr unsigned int TUNE_MAX_TRIAL_CANDIDATES { 4 };
|
||||
static constexpr unsigned int TUNE_MAX_TRIAL_CANDIDATES { 8 };
|
||||
|
||||
/**
|
||||
* @brief The maximum number of candidate partitionings tested for each encoding mode.
|
||||
*
|
||||
* This can be dynamically reduced by the compression quality preset.
|
||||
*/
|
||||
static constexpr unsigned int TUNE_MAX_PARTITIONING_CANDIDATES { 32 };
|
||||
|
||||
/**
|
||||
* @brief The maximum quant level using full angular endpoint search method.
|
||||
|
@ -147,10 +154,12 @@ static constexpr unsigned int TUNE_MAX_TRIAL_CANDIDATES { 4 };
|
|||
*/
|
||||
static constexpr unsigned int TUNE_MAX_ANGULAR_QUANT { 7 }; /* QUANT_12 */
|
||||
|
||||
|
||||
static_assert((BLOCK_MAX_TEXELS % ASTCENC_SIMD_WIDTH) == 0,
|
||||
"BLOCK_MAX_TEXELS must be multiple of ASTCENC_SIMD_WIDTH");
|
||||
|
||||
static_assert(BLOCK_MAX_TEXELS <= 216,
|
||||
"BLOCK_MAX_TEXELS must not be greater than 216");
|
||||
|
||||
static_assert((BLOCK_MAX_WEIGHTS % ASTCENC_SIMD_WIDTH) == 0,
|
||||
"BLOCK_MAX_WEIGHTS must be multiple of ASTCENC_SIMD_WIDTH");
|
||||
|
||||
|
@ -353,38 +362,50 @@ struct decimation_info
|
|||
/** @brief The number of stored weights in the Z dimension. */
|
||||
uint8_t weight_z;
|
||||
|
||||
/** @brief The number of stored weights that contribute to each texel, between 1 and 4. */
|
||||
/**
|
||||
* @brief The number of weights that contribute to each texel.
|
||||
* Value is between 1 and 4.
|
||||
*/
|
||||
uint8_t texel_weight_count[BLOCK_MAX_TEXELS];
|
||||
|
||||
/** @brief The weight index of the N weights that need to be interpolated for each texel. */
|
||||
uint8_t texel_weights_4t[4][BLOCK_MAX_TEXELS];
|
||||
/**
|
||||
* @brief The weight index of the N weights that are interpolated for each texel.
|
||||
* Stored transposed to improve vectorization.
|
||||
*/
|
||||
uint8_t texel_weights_tr[4][BLOCK_MAX_TEXELS];
|
||||
|
||||
/** @brief The bilinear interpolation weighting of the N input weights for each texel, between 0 and 16. */
|
||||
uint8_t texel_weights_int_4t[4][BLOCK_MAX_TEXELS];
|
||||
/**
|
||||
* @brief The bilinear contribution of the N weights that are interpolated for each texel.
|
||||
* Value is between 0 and 16, stored transposed to improve vectorization.
|
||||
*/
|
||||
uint8_t texel_weight_contribs_int_tr[4][BLOCK_MAX_TEXELS];
|
||||
|
||||
/** @brief The bilinear interpolation weighting of the N input weights for each texel, between 0 and 1. */
|
||||
alignas(ASTCENC_VECALIGN) float texel_weights_float_4t[4][BLOCK_MAX_TEXELS];
|
||||
/**
|
||||
* @brief The bilinear contribution of the N weights that are interpolated for each texel.
|
||||
* Value is between 0 and 1, stored transposed to improve vectorization.
|
||||
*/
|
||||
alignas(ASTCENC_VECALIGN) float texel_weight_contribs_float_tr[4][BLOCK_MAX_TEXELS];
|
||||
|
||||
/** @brief The number of texels that each stored weight contributes to. */
|
||||
uint8_t weight_texel_count[BLOCK_MAX_WEIGHTS];
|
||||
|
||||
/** @brief The list of weights that contribute to each texel. */
|
||||
uint8_t weight_texel[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
|
||||
|
||||
/** @brief The list of weight indices that contribute to each texel. */
|
||||
alignas(ASTCENC_VECALIGN) float weights_flt[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
|
||||
/**
|
||||
* @brief The list of texels that use a specific weight index.
|
||||
* Stored transposed to improve vectorization.
|
||||
*/
|
||||
uint8_t weight_texels_tr[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
|
||||
|
||||
/**
|
||||
* @brief Folded structure for faster access:
|
||||
* texel_weights_texel[i][j][.] = texel_weights[.][weight_texel[i][j]]
|
||||
* @brief The bilinear contribution to the N texels that use each weight.
|
||||
* Value is between 0 and 1, stored transposed to improve vectorization.
|
||||
*/
|
||||
uint8_t texel_weights_texel[BLOCK_MAX_WEIGHTS][BLOCK_MAX_TEXELS][4];
|
||||
alignas(ASTCENC_VECALIGN) float weights_texel_contribs_tr[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
|
||||
|
||||
/**
|
||||
* @brief Folded structure for faster access:
|
||||
* texel_weights_float_texel[i][j][.] = texel_weights_float[.][weight_texel[i][j]]
|
||||
* @brief The bilinear contribution to the Nth texel that uses each weight.
|
||||
* Value is between 0 and 1, stored transposed to improve vectorization.
|
||||
*/
|
||||
float texel_weights_float_texel[BLOCK_MAX_WEIGHTS][BLOCK_MAX_TEXELS][4];
|
||||
float texel_contrib_for_weight[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -579,13 +600,6 @@ struct block_size_descriptor
|
|||
/** @brief The active texels for k-means partition selection. */
|
||||
uint8_t kmeans_texels[BLOCK_MAX_KMEANS_TEXELS];
|
||||
|
||||
/**
|
||||
* @brief Is 0 if this 2-partition is valid for compression 255 otherwise.
|
||||
*
|
||||
* Indexed by remapped index, not physical index.
|
||||
*/
|
||||
uint8_t partitioning_valid_2[BLOCK_MAX_PARTITIONINGS];
|
||||
|
||||
/**
|
||||
* @brief The canonical 2-partition coverage pattern used during block partition search.
|
||||
*
|
||||
|
@ -593,13 +607,6 @@ struct block_size_descriptor
|
|||
*/
|
||||
uint64_t coverage_bitmaps_2[BLOCK_MAX_PARTITIONINGS][2];
|
||||
|
||||
/**
|
||||
* @brief Is 0 if this 3-partition is valid for compression 255 otherwise.
|
||||
*
|
||||
* Indexed by remapped index, not physical index.
|
||||
*/
|
||||
uint8_t partitioning_valid_3[BLOCK_MAX_PARTITIONINGS];
|
||||
|
||||
/**
|
||||
* @brief The canonical 3-partition coverage pattern used during block partition search.
|
||||
*
|
||||
|
@ -607,13 +614,6 @@ struct block_size_descriptor
|
|||
*/
|
||||
uint64_t coverage_bitmaps_3[BLOCK_MAX_PARTITIONINGS][3];
|
||||
|
||||
/**
|
||||
* @brief Is 0 if this 4-partition is valid for compression 255 otherwise.
|
||||
*
|
||||
* Indexed by remapped index, not physical index.
|
||||
*/
|
||||
uint8_t partitioning_valid_4[BLOCK_MAX_PARTITIONINGS];
|
||||
|
||||
/**
|
||||
* @brief The canonical 4-partition coverage pattern used during block partition search.
|
||||
*
|
||||
|
@ -1022,9 +1022,6 @@ struct dt_init_working_buffers
|
|||
*/
|
||||
struct quant_and_transfer_table
|
||||
{
|
||||
/** @brief The quantization level used. */
|
||||
quant_method method;
|
||||
|
||||
/** @brief The unscrambled unquantized value. */
|
||||
int8_t quant_to_unquant[32];
|
||||
|
||||
|
@ -1336,20 +1333,32 @@ bool is_legal_3d_block_size(
|
|||
/**
|
||||
* @brief The precomputed table for quantizing color values.
|
||||
*
|
||||
* Returned value is in the ASTC BISE scrambled order.
|
||||
* Converts unquant value in 0-255 range into quant value in 0-255 range.
|
||||
* No BISE scrambling is applied at this stage.
|
||||
*
|
||||
* Indexed by [quant_mode - 4][data_value].
|
||||
*/
|
||||
extern const uint8_t color_quant_tables[17][256];
|
||||
extern const uint8_t color_unquant_to_uquant_tables[17][256];
|
||||
|
||||
/**
|
||||
* @brief The precomputed table for unquantizing color values.
|
||||
* @brief The precomputed table for packing quantized color values.
|
||||
*
|
||||
* Returned value is in the ASTC BISE scrambled order.
|
||||
* Converts quant value in 0-255 range into packed quant value in 0-N range,
|
||||
* with BISE scrambling applied.
|
||||
*
|
||||
* Indexed by [quant_mode - 4][data_value].
|
||||
*/
|
||||
extern const uint8_t color_unquant_tables[17][256];
|
||||
extern const uint8_t color_uquant_to_scrambled_pquant_tables[17][256];
|
||||
|
||||
/**
|
||||
* @brief The precomputed table for unpacking color values.
|
||||
*
|
||||
* Converts quant value in 0-N range into unpacked value in 0-255 range,
|
||||
* with BISE unscrambling applied.
|
||||
*
|
||||
* Indexed by [quant_mode - 4][data_value].
|
||||
*/
|
||||
extern const uint8_t* color_scrambled_pquant_to_uquant_tables[17];
|
||||
|
||||
/**
|
||||
* @brief The precomputed quant mode storage table.
|
||||
|
@ -1366,11 +1375,11 @@ extern const int8_t quant_mode_table[10][128];
|
|||
* Note that BISE can return strings that are not a whole number of bytes in length, and ASTC can
|
||||
* start storing strings in a block at arbitrary bit offsets in the encoded data.
|
||||
*
|
||||
* @param quant_level The BISE alphabet size.
|
||||
* @param character_count The number of characters in the string.
|
||||
* @param input_data The unpacked string, one byte per character.
|
||||
* @param[in,out] output_data The output packed string.
|
||||
* @param bit_offset The starting offset in the output storage.
|
||||
* @param quant_level The BISE alphabet size.
|
||||
* @param character_count The number of characters in the string.
|
||||
* @param input_data The unpacked string, one byte per character.
|
||||
* @param[in,out] output_data The output packed string.
|
||||
* @param bit_offset The starting offset in the output storage.
|
||||
*/
|
||||
void encode_ise(
|
||||
quant_method quant_level,
|
||||
|
@ -1457,11 +1466,11 @@ void compute_avgs_and_dirs_3_comp(
|
|||
* This is a specialization of @c compute_avgs_and_dirs_3_comp where the omitted component is
|
||||
* always alpha, a common case during partition search.
|
||||
*
|
||||
* @param pi The partition info for the current trial.
|
||||
* @param blk The image block color data to be compressed.
|
||||
* @param[out] pm The output partition metrics.
|
||||
* - Only pi.partition_count array entries actually get initialized.
|
||||
* - Direction vectors @c pm.dir are not normalized.
|
||||
* @param pi The partition info for the current trial.
|
||||
* @param blk The image block color data to be compressed.
|
||||
* @param[out] pm The output partition metrics.
|
||||
* - Only pi.partition_count array entries actually get initialized.
|
||||
* - Direction vectors @c pm.dir are not normalized.
|
||||
*/
|
||||
void compute_avgs_and_dirs_3_comp_rgb(
|
||||
const partition_info& pi,
|
||||
|
@ -1492,11 +1501,11 @@ void compute_avgs_and_dirs_4_comp(
|
|||
*
|
||||
* This function computes the squared error when using these two representations.
|
||||
*
|
||||
* @param pi The partition info for the current trial.
|
||||
* @param blk The image block color data to be compressed.
|
||||
* @param[in,out] plines Processed line inputs, and line length outputs.
|
||||
* @param[out] uncor_error The cumulative error for using the uncorrelated line.
|
||||
* @param[out] samec_error The cumulative error for using the same chroma line.
|
||||
* @param pi The partition info for the current trial.
|
||||
* @param blk The image block color data to be compressed.
|
||||
* @param[in,out] plines Processed line inputs, and line length outputs.
|
||||
* @param[out] uncor_error The cumulative error for using the uncorrelated line.
|
||||
* @param[out] samec_error The cumulative error for using the same chroma line.
|
||||
*/
|
||||
void compute_error_squared_rgb(
|
||||
const partition_info& pi,
|
||||
|
@ -1541,18 +1550,23 @@ void compute_error_squared_rgba(
|
|||
* candidates; one assuming data has uncorrelated chroma and one assuming the
|
||||
* data has correlated chroma. The best candidate is returned first in the list.
|
||||
*
|
||||
* @param bsd The block size information.
|
||||
* @param blk The image block color data to compress.
|
||||
* @param partition_count The number of partitions in the block.
|
||||
* @param partition_search_limit The number of candidate partition encodings to trial.
|
||||
* @param[out] best_partitions The best partition candidates.
|
||||
* @param bsd The block size information.
|
||||
* @param blk The image block color data to compress.
|
||||
* @param partition_count The number of partitions in the block.
|
||||
* @param partition_search_limit The number of candidate partition encodings to trial.
|
||||
* @param[out] best_partitions The best partition candidates.
|
||||
* @param requested_candidates The number of requested partitionings. May return fewer if
|
||||
* candidates are not available.
|
||||
*
|
||||
* @return The actual number of candidates returned.
|
||||
*/
|
||||
void find_best_partition_candidates(
|
||||
unsigned int find_best_partition_candidates(
|
||||
const block_size_descriptor& bsd,
|
||||
const image_block& blk,
|
||||
unsigned int partition_count,
|
||||
unsigned int partition_search_limit,
|
||||
unsigned int best_partitions[2]);
|
||||
unsigned int best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES],
|
||||
unsigned int requested_candidates);
|
||||
|
||||
/* ============================================================================
|
||||
Functionality for managing images and image related data.
|
||||
|
@ -1566,10 +1580,10 @@ void find_best_partition_candidates(
|
|||
*
|
||||
* Results are written back into @c img->input_alpha_averages.
|
||||
*
|
||||
* @param img The input image data, also holds output data.
|
||||
* @param alpha_kernel_radius The kernel radius (in pixels) for alpha mods.
|
||||
* @param swz Input data component swizzle.
|
||||
* @param[out] ag The average variance arguments to init.
|
||||
* @param img The input image data, also holds output data.
|
||||
* @param alpha_kernel_radius The kernel radius (in pixels) for alpha mods.
|
||||
* @param swz Input data component swizzle.
|
||||
* @param[out] ag The average variance arguments to init.
|
||||
*
|
||||
* @return The number of tasks in the processing stage.
|
||||
*/
|
||||
|
@ -1787,13 +1801,13 @@ float compute_error_of_weight_set_2planes(
|
|||
* The user requests a base color endpoint mode in @c format, but the quantizer may choose a
|
||||
* delta-based representation. It will report back the format variant it actually used.
|
||||
*
|
||||
* @param color0 The input unquantized color0 endpoint for absolute endpoint pairs.
|
||||
* @param color1 The input unquantized color1 endpoint for absolute endpoint pairs.
|
||||
* @param rgbs_color The input unquantized RGBS variant endpoint for same chroma endpoints.
|
||||
* @param rgbo_color The input unquantized RGBS variant endpoint for HDR endpoints..
|
||||
* @param format The desired base format.
|
||||
* @param[out] output The output storage for the quantized colors/
|
||||
* @param quant_level The quantization level requested.
|
||||
* @param color0 The input unquantized color0 endpoint for absolute endpoint pairs.
|
||||
* @param color1 The input unquantized color1 endpoint for absolute endpoint pairs.
|
||||
* @param rgbs_color The input unquantized RGBS variant endpoint for same chroma endpoints.
|
||||
* @param rgbo_color The input unquantized RGBS variant endpoint for HDR endpoints.
|
||||
* @param format The desired base format.
|
||||
* @param[out] output The output storage for the quantized colors/
|
||||
* @param quant_level The quantization level requested.
|
||||
*
|
||||
* @return The actual endpoint mode used.
|
||||
*/
|
||||
|
@ -1807,11 +1821,12 @@ uint8_t pack_color_endpoints(
|
|||
quant_method quant_level);
|
||||
|
||||
/**
|
||||
* @brief Unpack a single pair of encoded and quantized color endpoints.
|
||||
* @brief Unpack a single pair of encoded endpoints.
|
||||
*
|
||||
* Endpoints must be unscrambled and converted into the 0-255 range before calling this functions.
|
||||
*
|
||||
* @param decode_mode The decode mode (LDR, HDR).
|
||||
* @param format The color endpoint mode used.
|
||||
* @param quant_level The quantization level used.
|
||||
* @param input The raw array of encoded input integers. The length of this array
|
||||
* depends on @c format; it can be safely assumed to be large enough.
|
||||
* @param[out] rgb_hdr Is the endpoint using HDR for the RGB channels?
|
||||
|
@ -1822,7 +1837,6 @@ uint8_t pack_color_endpoints(
|
|||
void unpack_color_endpoints(
|
||||
astcenc_profile decode_mode,
|
||||
int format,
|
||||
quant_method quant_level,
|
||||
const uint8_t* input,
|
||||
bool& rgb_hdr,
|
||||
bool& alpha_hdr,
|
||||
|
@ -1894,13 +1908,13 @@ unsigned int compute_ideal_endpoint_formats(
|
|||
* As we quantize and decimate weights the optimal endpoint colors may change slightly, so we must
|
||||
* recompute the ideal colors for a specific weight set.
|
||||
*
|
||||
* @param blk The image block color data to compress.
|
||||
* @param pi The partition info for the current trial.
|
||||
* @param di The weight grid decimation table.
|
||||
* @param blk The image block color data to compress.
|
||||
* @param pi The partition info for the current trial.
|
||||
* @param di The weight grid decimation table.
|
||||
* @param dec_weights_uquant The quantized weight set.
|
||||
* @param[in,out] ep The color endpoints (modifed in place).
|
||||
* @param[out] rgbs_vectors The RGB+scale vectors for LDR blocks.
|
||||
* @param[out] rgbo_vectors The RGB+offset vectors for HDR blocks.
|
||||
* @param[in,out] ep The color endpoints (modifed in place).
|
||||
* @param[out] rgbs_vectors The RGB+scale vectors for LDR blocks.
|
||||
* @param[out] rgbo_vectors The RGB+offset vectors for HDR blocks.
|
||||
*/
|
||||
void recompute_ideal_colors_1plane(
|
||||
const image_block& blk,
|
||||
|
@ -1917,15 +1931,15 @@ void recompute_ideal_colors_1plane(
|
|||
* As we quantize and decimate weights the optimal endpoint colors may change slightly, so we must
|
||||
* recompute the ideal colors for a specific weight set.
|
||||
*
|
||||
* @param blk The image block color data to compress.
|
||||
* @param bsd The block_size descriptor.
|
||||
* @param di The weight grid decimation table.
|
||||
* @param blk The image block color data to compress.
|
||||
* @param bsd The block_size descriptor.
|
||||
* @param di The weight grid decimation table.
|
||||
* @param dec_weights_uquant_plane1 The quantized weight set for plane 1.
|
||||
* @param dec_weights_uquant_plane2 The quantized weight set for plane 2.
|
||||
* @param[in,out] ep The color endpoints (modifed in place).
|
||||
* @param[out] rgbs_vector The RGB+scale color for LDR blocks.
|
||||
* @param[out] rgbo_vector The RGB+offset color for HDR blocks.
|
||||
* @param plane2_component The component assigned to plane 2.
|
||||
* @param[in,out] ep The color endpoints (modifed in place).
|
||||
* @param[out] rgbs_vector The RGB+scale color for LDR blocks.
|
||||
* @param[out] rgbo_vector The RGB+offset color for HDR blocks.
|
||||
* @param plane2_component The component assigned to plane 2.
|
||||
*/
|
||||
void recompute_ideal_colors_2planes(
|
||||
const image_block& blk,
|
||||
|
@ -1946,15 +1960,13 @@ void prepare_angular_tables();
|
|||
/**
|
||||
* @brief Compute the angular endpoints for one plane for each block mode.
|
||||
*
|
||||
* @param tune_low_weight_limit Weight count cutoff below which we use simpler searches.
|
||||
* @param only_always Only consider block modes that are always enabled.
|
||||
* @param bsd The block size descriptor for the current trial.
|
||||
* @param dec_weight_ideal_value The ideal decimated unquantized weight values.
|
||||
* @param max_weight_quant The maximum block mode weight quantization allowed.
|
||||
* @param[out] tmpbuf Preallocated scratch buffers for the compressor.
|
||||
* @param only_always Only consider block modes that are always enabled.
|
||||
* @param bsd The block size descriptor for the current trial.
|
||||
* @param dec_weight_ideal_value The ideal decimated unquantized weight values.
|
||||
* @param max_weight_quant The maximum block mode weight quantization allowed.
|
||||
* @param[out] tmpbuf Preallocated scratch buffers for the compressor.
|
||||
*/
|
||||
void compute_angular_endpoints_1plane(
|
||||
unsigned int tune_low_weight_limit,
|
||||
bool only_always,
|
||||
const block_size_descriptor& bsd,
|
||||
const float* dec_weight_ideal_value,
|
||||
|
@ -1964,14 +1976,12 @@ void compute_angular_endpoints_1plane(
|
|||
/**
|
||||
* @brief Compute the angular endpoints for two planes for each block mode.
|
||||
*
|
||||
* @param tune_low_weight_limit Weight count cutoff below which we use simpler searches.
|
||||
* @param bsd The block size descriptor for the current trial.
|
||||
* @param dec_weight_ideal_value The ideal decimated unquantized weight values.
|
||||
* @param max_weight_quant The maximum block mode weight quantization allowed.
|
||||
* @param[out] tmpbuf Preallocated scratch buffers for the compressor.
|
||||
* @param bsd The block size descriptor for the current trial.
|
||||
* @param dec_weight_ideal_value The ideal decimated unquantized weight values.
|
||||
* @param max_weight_quant The maximum block mode weight quantization allowed.
|
||||
* @param[out] tmpbuf Preallocated scratch buffers for the compressor.
|
||||
*/
|
||||
void compute_angular_endpoints_2planes(
|
||||
unsigned int tune_low_weight_limit,
|
||||
const block_size_descriptor& bsd,
|
||||
const float* dec_weight_ideal_value,
|
||||
unsigned int max_weight_quant,
|
||||
|
@ -2183,18 +2193,4 @@ void aligned_free(T* ptr)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline void dump_weights(const char* label, uint8_t* weights, int weight_count)
|
||||
{
|
||||
printf("%s\n", label);
|
||||
vint lane = vint::lane_id();
|
||||
for (int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH)
|
||||
{
|
||||
vmask mask = lane < vint(weight_count);
|
||||
vint val(weights + i);
|
||||
val = select(vint::zero(), val, mask);
|
||||
print(val);
|
||||
lane += vint(ASTCENC_SIMD_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2011-2022 Arm Limited
|
||||
// Copyright 2011-2023 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -21,6 +21,9 @@
|
|||
|
||||
#include "astcenc_internal.h"
|
||||
|
||||
/** @brief The number of 64-bit words needed to represent a canonical partition bit pattern. */
|
||||
#define BIT_PATTERN_WORDS (((ASTCENC_BLOCK_MAX_TEXELS * 2) + 63) / 64)
|
||||
|
||||
/**
|
||||
* @brief Generate a canonical representation of a partition pattern.
|
||||
*
|
||||
|
@ -28,22 +31,22 @@
|
|||
* the remapped texel index. Remapping ensures that we only match on the partition pattern,
|
||||
* independent of the partition order generated by the hash.
|
||||
*
|
||||
* @param texel_count The number of texels in the block.
|
||||
* @param partition_of_texel The partition assignments, in hash order.
|
||||
* @param[out] bit_pattern The output bit pattern representation.
|
||||
* @param texel_count The number of texels in the block.
|
||||
* @param partition_of_texel The partition assignments, in hash order.
|
||||
* @param[out] bit_pattern The output bit pattern representation.
|
||||
*/
|
||||
static void generate_canonical_partitioning(
|
||||
unsigned int texel_count,
|
||||
const uint8_t* partition_of_texel,
|
||||
uint64_t bit_pattern[7]
|
||||
uint64_t bit_pattern[BIT_PATTERN_WORDS]
|
||||
) {
|
||||
// Clear the pattern
|
||||
for (unsigned int i = 0; i < 7; i++)
|
||||
for (unsigned int i = 0; i < BIT_PATTERN_WORDS; i++)
|
||||
{
|
||||
bit_pattern[i] = 0;
|
||||
}
|
||||
|
||||
// Store a mapping to reorder the raw partitions so that the the partitions are ordered such
|
||||
// Store a mapping to reorder the raw partitions so that the partitions are ordered such
|
||||
// that the lowest texel index in partition N is smaller than the lowest texel index in
|
||||
// partition N + 1.
|
||||
int mapped_index[BLOCK_MAX_PARTITIONS];
|
||||
|
@ -76,19 +79,35 @@ static void generate_canonical_partitioning(
|
|||
* @return @c true if the patterns are the same, @c false otherwise.
|
||||
*/
|
||||
static bool compare_canonical_partitionings(
|
||||
const uint64_t part1[7],
|
||||
const uint64_t part2[7]
|
||||
const uint64_t part1[BIT_PATTERN_WORDS],
|
||||
const uint64_t part2[BIT_PATTERN_WORDS]
|
||||
) {
|
||||
return (part1[0] == part2[0]) && (part1[1] == part2[1]) &&
|
||||
(part1[2] == part2[2]) && (part1[3] == part2[3]) &&
|
||||
(part1[4] == part2[4]) && (part1[5] == part2[5]) &&
|
||||
(part1[6] == part2[6]);
|
||||
return (part1[0] == part2[0])
|
||||
#if BIT_PATTERN_WORDS > 1
|
||||
&& (part1[1] == part2[1])
|
||||
#endif
|
||||
#if BIT_PATTERN_WORDS > 2
|
||||
&& (part1[2] == part2[2])
|
||||
#endif
|
||||
#if BIT_PATTERN_WORDS > 3
|
||||
&& (part1[3] == part2[3])
|
||||
#endif
|
||||
#if BIT_PATTERN_WORDS > 4
|
||||
&& (part1[4] == part2[4])
|
||||
#endif
|
||||
#if BIT_PATTERN_WORDS > 5
|
||||
&& (part1[5] == part2[5])
|
||||
#endif
|
||||
#if BIT_PATTERN_WORDS > 6
|
||||
&& (part1[6] == part2[6])
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hash function used for procedural partition assignment.
|
||||
*
|
||||
* @param inp The hash seed.
|
||||
* @param inp The hash seed.
|
||||
*
|
||||
* @return The hashed value.
|
||||
*/
|
||||
|
@ -116,7 +135,7 @@ static uint32_t hash52(
|
|||
* @param y The texel Y coordinate in the block.
|
||||
* @param z The texel Z coordinate in the block.
|
||||
* @param partition_count The total partition count of this encoding.
|
||||
* @param small_block @c true if the blockhas fewer than 32 texels.
|
||||
* @param small_block @c true if the block has fewer than 32 texels.
|
||||
*
|
||||
* @return The assigned partition index for this texel.
|
||||
*/
|
||||
|
@ -320,21 +339,17 @@ static bool generate_one_partition_info_entry(
|
|||
|
||||
// Populate the coverage bitmaps for 2/3/4 partitions
|
||||
uint64_t* bitmaps { nullptr };
|
||||
uint8_t* valids { nullptr };
|
||||
if (partition_count == 2)
|
||||
{
|
||||
bitmaps = bsd.coverage_bitmaps_2[partition_remap_index];
|
||||
valids = bsd.partitioning_valid_2;
|
||||
}
|
||||
else if (partition_count == 3)
|
||||
{
|
||||
bitmaps = bsd.coverage_bitmaps_3[partition_remap_index];
|
||||
valids = bsd.partitioning_valid_3;
|
||||
}
|
||||
else if (partition_count == 4)
|
||||
{
|
||||
bitmaps = bsd.coverage_bitmaps_4[partition_remap_index];
|
||||
valids = bsd.partitioning_valid_4;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < BLOCK_MAX_PARTITIONS; i++)
|
||||
|
@ -347,9 +362,7 @@ static bool generate_one_partition_info_entry(
|
|||
|
||||
if (bitmaps)
|
||||
{
|
||||
// Populate the bitmap validity mask
|
||||
valids[partition_remap_index] = valid ? 0 : 255;
|
||||
|
||||
// Populate the partition coverage bitmap
|
||||
for (unsigned int i = 0; i < partition_count; i++)
|
||||
{
|
||||
bitmaps[i] = 0ULL;
|
||||
|
@ -374,12 +387,6 @@ static void build_partition_table_for_one_partition_count(
|
|||
partition_info* ptab,
|
||||
uint64_t* canonical_patterns
|
||||
) {
|
||||
uint8_t* partitioning_valid[3] {
|
||||
bsd.partitioning_valid_2,
|
||||
bsd.partitioning_valid_3,
|
||||
bsd.partitioning_valid_4
|
||||
};
|
||||
|
||||
unsigned int next_index = 0;
|
||||
bsd.partitioning_count_selected[partition_count - 1] = 0;
|
||||
bsd.partitioning_count_all[partition_count - 1] = 0;
|
||||
|
@ -397,7 +404,7 @@ static void build_partition_table_for_one_partition_count(
|
|||
|
||||
// Tracker for things we built in the first iteration
|
||||
uint8_t build[BLOCK_MAX_PARTITIONINGS] { 0 };
|
||||
for (unsigned int x = 0; x < max_iter; x++)
|
||||
for (unsigned int x = 0; x < max_iter; x++)
|
||||
{
|
||||
for (unsigned int i = 0; i < BLOCK_MAX_PARTITIONINGS; i++)
|
||||
{
|
||||
|
@ -413,11 +420,11 @@ static void build_partition_table_for_one_partition_count(
|
|||
continue;
|
||||
}
|
||||
|
||||
generate_canonical_partitioning(bsd.texel_count, ptab[next_index].partition_of_texel, canonical_patterns + next_index * 7);
|
||||
generate_canonical_partitioning(bsd.texel_count, ptab[next_index].partition_of_texel, canonical_patterns + next_index * BIT_PATTERN_WORDS);
|
||||
bool keep_canonical = true;
|
||||
for (unsigned int j = 0; j < next_index; j++)
|
||||
{
|
||||
bool match = compare_canonical_partitionings(canonical_patterns + 7 * next_index, canonical_patterns + 7 * j);
|
||||
bool match = compare_canonical_partitionings(canonical_patterns + next_index * BIT_PATTERN_WORDS, canonical_patterns + j * BIT_PATTERN_WORDS);
|
||||
if (match)
|
||||
{
|
||||
keep_canonical = false;
|
||||
|
@ -442,7 +449,6 @@ static void build_partition_table_for_one_partition_count(
|
|||
{
|
||||
bsd.partitioning_packed_index[partition_count - 2][i] = static_cast<uint16_t>(next_index);
|
||||
bsd.partitioning_count_all[partition_count - 1]++;
|
||||
partitioning_valid[partition_count - 2][next_index] = 255;
|
||||
next_index++;
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +471,8 @@ void init_partition_tables(
|
|||
bsd.partitioning_count_selected[0] = 1;
|
||||
bsd.partitioning_count_all[0] = 1;
|
||||
|
||||
uint64_t* canonical_patterns = new uint64_t[BLOCK_MAX_PARTITIONINGS * 7];
|
||||
uint64_t* canonical_patterns = new uint64_t[BLOCK_MAX_PARTITIONINGS * BIT_PATTERN_WORDS];
|
||||
|
||||
build_partition_table_for_one_partition_count(bsd, can_omit_partitionings, partition_count_cutoff, 2, par_tab2, canonical_patterns);
|
||||
build_partition_table_for_one_partition_count(bsd, can_omit_partitionings, partition_count_cutoff, 3, par_tab3, canonical_patterns);
|
||||
build_partition_table_for_one_partition_count(bsd, can_omit_partitionings, partition_count_cutoff, 4, par_tab4, canonical_patterns);
|
||||
|
|
|
@ -1166,11 +1166,11 @@ const float *get_2d_percentile_table(
|
|||
unsigned int xdim,
|
||||
unsigned int ydim
|
||||
) {
|
||||
float* unpacked_table = new float[2048];
|
||||
float* unpacked_table = new float[WEIGHTS_MAX_BLOCK_MODES];
|
||||
const packed_percentile_table *apt = get_packed_table(xdim, ydim);
|
||||
|
||||
// Set the default percentile
|
||||
for (unsigned int i = 0; i < 2048; i++)
|
||||
for (unsigned int i = 0; i < WEIGHTS_MAX_BLOCK_MODES; i++)
|
||||
{
|
||||
unpacked_table[i] = 1.0f;
|
||||
}
|
||||
|
|
|
@ -325,11 +325,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level(
|
|||
) {
|
||||
int partition_size = pi.partition_texel_count[partition_index];
|
||||
|
||||
static const float baseline_quant_error[21] {
|
||||
(65536.0f * 65536.0f / 18.0f), // 2 values, 1 step
|
||||
(65536.0f * 65536.0f / 18.0f) / (2 * 2), // 3 values, 2 steps
|
||||
(65536.0f * 65536.0f / 18.0f) / (3 * 3), // 4 values, 3 steps
|
||||
(65536.0f * 65536.0f / 18.0f) / (4 * 4), // 5 values
|
||||
static const float baseline_quant_error[21 - QUANT_6] {
|
||||
(65536.0f * 65536.0f / 18.0f) / (5 * 5),
|
||||
(65536.0f * 65536.0f / 18.0f) / (7 * 7),
|
||||
(65536.0f * 65536.0f / 18.0f) / (9 * 9),
|
||||
|
@ -528,7 +524,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level(
|
|||
// The base_quant_error should depend on the scale-factor that would be used during
|
||||
// actual encode of the color value
|
||||
|
||||
float base_quant_error = baseline_quant_error[i] * static_cast<float>(partition_size);
|
||||
float base_quant_error = baseline_quant_error[i - QUANT_6] * static_cast<float>(partition_size);
|
||||
float rgb_quantization_error = error_weight_rgbsum * base_quant_error * 2.0f;
|
||||
float alpha_quantization_error = error_weight.lane<3>() * base_quant_error * 2.0f;
|
||||
float rgba_quantization_error = rgb_quantization_error + alpha_quantization_error;
|
||||
|
@ -591,7 +587,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level(
|
|||
error_scale_oe_rgb = 1.0f;
|
||||
}
|
||||
|
||||
float base_quant_error = baseline_quant_error[i];
|
||||
float base_quant_error = baseline_quant_error[i - QUANT_6];
|
||||
float quant_error_rgb = base_quant_error_rgb * base_quant_error;
|
||||
float quant_error_rgba = base_quant_error_rgba * base_quant_error;
|
||||
|
||||
|
@ -1136,22 +1132,19 @@ unsigned int compute_ideal_endpoint_formats(
|
|||
uint8_t (&best_ep_formats)[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS] = tmpbuf.best_ep_formats;
|
||||
|
||||
// Ensure that the first iteration understep contains data that will never be picked
|
||||
vfloat clear_error(ERROR_CALC_DEFAULT);
|
||||
vint clear_quant(0);
|
||||
|
||||
unsigned int packed_start_block_mode = round_down_to_simd_multiple_vla(start_block_mode);
|
||||
for (unsigned int i = packed_start_block_mode; i < start_block_mode; i++)
|
||||
{
|
||||
errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
|
||||
best_quant_levels[i] = QUANT_2;
|
||||
best_quant_levels_mod[i] = QUANT_2;
|
||||
}
|
||||
storea(clear_error, errors_of_best_combination + packed_start_block_mode);
|
||||
store_nbytes(clear_quant, best_quant_levels + packed_start_block_mode);
|
||||
store_nbytes(clear_quant, best_quant_levels_mod + packed_start_block_mode);
|
||||
|
||||
// Ensure that last iteration overstep contains data that will never be picked
|
||||
const unsigned int packed_end_block_mode = round_up_to_simd_multiple_vla(end_block_mode);
|
||||
for (unsigned int i = end_block_mode; i < packed_end_block_mode; i++)
|
||||
{
|
||||
errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
|
||||
best_quant_levels[i] = QUANT_2;
|
||||
best_quant_levels_mod[i] = QUANT_2;
|
||||
}
|
||||
unsigned int packed_end_block_mode = round_down_to_simd_multiple_vla(end_block_mode - 1);
|
||||
storea(clear_error, errors_of_best_combination + packed_end_block_mode);
|
||||
store_nbytes(clear_quant, best_quant_levels + packed_end_block_mode);
|
||||
store_nbytes(clear_quant, best_quant_levels_mod + packed_end_block_mode);
|
||||
|
||||
// Track a scalar best to avoid expensive search at least once ...
|
||||
float error_of_best_combination = ERROR_CALC_DEFAULT;
|
||||
|
@ -1160,7 +1153,7 @@ unsigned int compute_ideal_endpoint_formats(
|
|||
// The block contains 1 partition
|
||||
if (partition_count == 1)
|
||||
{
|
||||
for (unsigned int i = start_block_mode; i < end_block_mode; ++i)
|
||||
for (unsigned int i = start_block_mode; i < end_block_mode; i++)
|
||||
{
|
||||
if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
|
||||
{
|
||||
|
@ -1193,7 +1186,7 @@ unsigned int compute_ideal_endpoint_formats(
|
|||
best_error, format_of_choice, combined_best_error, formats_of_choice);
|
||||
|
||||
assert(start_block_mode == 0);
|
||||
for (unsigned int i = 0; i < end_block_mode; ++i)
|
||||
for (unsigned int i = 0; i < end_block_mode; i++)
|
||||
{
|
||||
if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
|
||||
{
|
||||
|
@ -1226,7 +1219,7 @@ unsigned int compute_ideal_endpoint_formats(
|
|||
best_error, format_of_choice, combined_best_error, formats_of_choice);
|
||||
|
||||
assert(start_block_mode == 0);
|
||||
for (unsigned int i = 0; i < end_block_mode; ++i)
|
||||
for (unsigned int i = 0; i < end_block_mode; i++)
|
||||
{
|
||||
if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
|
||||
{
|
||||
|
@ -1260,7 +1253,7 @@ unsigned int compute_ideal_endpoint_formats(
|
|||
best_error, format_of_choice, combined_best_error, formats_of_choice);
|
||||
|
||||
assert(start_block_mode == 0);
|
||||
for (unsigned int i = 0; i < end_block_mode; ++i)
|
||||
for (unsigned int i = 0; i < end_block_mode; i++)
|
||||
{
|
||||
if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2020-2021 Arm Limited
|
||||
// Copyright 2020-2022 Arm Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
|
@ -47,7 +47,7 @@ static bool g_cpu_has_f16c { false };
|
|||
============================================================================ */
|
||||
#if !defined(__clang__) && defined(_MSC_VER)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
|
||||
/**
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -265,13 +265,15 @@ void symbolic_to_physical(
|
|||
// Encode the color components
|
||||
uint8_t values_to_encode[32];
|
||||
int valuecount_to_encode = 0;
|
||||
|
||||
const uint8_t* pack_table = color_uquant_to_scrambled_pquant_tables[scb.quant_mode - QUANT_6];
|
||||
for (unsigned int i = 0; i < scb.partition_count; i++)
|
||||
{
|
||||
int vals = 2 * (scb.color_formats[i] >> 2) + 2;
|
||||
assert(vals <= 8);
|
||||
for (int j = 0; j < vals; j++)
|
||||
{
|
||||
values_to_encode[j + valuecount_to_encode] = scb.color_values[i][j];
|
||||
values_to_encode[j + valuecount_to_encode] = pack_table[scb.color_values[i][j]];
|
||||
}
|
||||
valuecount_to_encode += vals;
|
||||
}
|
||||
|
@ -369,12 +371,15 @@ void physical_to_symbolic(
|
|||
const auto& di = bsd.get_decimation_info(bm.decimation_mode);
|
||||
|
||||
int weight_count = di.weight_count;
|
||||
promise(weight_count > 0);
|
||||
|
||||
quant_method weight_quant_method = static_cast<quant_method>(bm.quant_mode);
|
||||
int is_dual_plane = bm.is_dual_plane;
|
||||
|
||||
int real_weight_count = is_dual_plane ? 2 * weight_count : weight_count;
|
||||
|
||||
int partition_count = read_bits(2, 11, pcb.data) + 1;
|
||||
promise(partition_count > 0);
|
||||
|
||||
scb.block_mode = static_cast<uint16_t>(block_mode);
|
||||
scb.partition_count = static_cast<uint8_t>(partition_count);
|
||||
|
@ -503,22 +508,25 @@ void physical_to_symbolic(
|
|||
|
||||
// Unpack the integer color values and assign to endpoints
|
||||
scb.quant_mode = static_cast<quant_method>(color_quant_level);
|
||||
|
||||
uint8_t values_to_decode[32];
|
||||
decode_ise(static_cast<quant_method>(color_quant_level), color_integer_count, pcb.data,
|
||||
values_to_decode, (partition_count == 1 ? 17 : 19 + PARTITION_INDEX_BITS));
|
||||
|
||||
int valuecount_to_decode = 0;
|
||||
const uint8_t* unpack_table = color_scrambled_pquant_to_uquant_tables[scb.quant_mode - QUANT_6];
|
||||
for (int i = 0; i < partition_count; i++)
|
||||
{
|
||||
int vals = 2 * (color_formats[i] >> 2) + 2;
|
||||
for (int j = 0; j < vals; j++)
|
||||
{
|
||||
scb.color_values[i][j] = values_to_decode[j + valuecount_to_decode];
|
||||
scb.color_values[i][j] = unpack_table[values_to_decode[j + valuecount_to_decode]];
|
||||
}
|
||||
valuecount_to_decode += vals;
|
||||
}
|
||||
|
||||
// Fetch component for second-plane in the case of dual plane of weights.
|
||||
scb.plane2_component = -1;
|
||||
if (is_dual_plane)
|
||||
{
|
||||
scb.plane2_component = static_cast<int8_t>(read_bits(2, below_weights_pos - 2, pcb.data));
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* with that is available at compile time. The current vector width is
|
||||
* accessible for e.g. loop strides via the ASTCENC_SIMD_WIDTH constant.
|
||||
*
|
||||
* Explicit scalar types are acessible via the vint1, vfloat1, vmask1 types.
|
||||
* Explicit scalar types are accessible via the vint1, vfloat1, vmask1 types.
|
||||
* These are provided primarily for prototyping and algorithm debug of VLA
|
||||
* implementations.
|
||||
*
|
||||
|
@ -402,7 +402,7 @@ static ASTCENC_SIMD_INLINE vint4 clz(vint4 a)
|
|||
// the original integer value into a 2^N encoding we can recover easily.
|
||||
|
||||
// Convert to float without risk of rounding up by keeping only top 8 bits.
|
||||
// This trick is is guranteed to keep top 8 bits and clear the 9th.
|
||||
// This trick is is guaranteed to keep top 8 bits and clear the 9th.
|
||||
a = (~lsr<8>(a)) & a;
|
||||
a = float_as_int(int_to_float(a));
|
||||
|
||||
|
@ -416,7 +416,7 @@ static ASTCENC_SIMD_INLINE vint4 clz(vint4 a)
|
|||
/**
|
||||
* @brief Return lanewise 2^a for each lane in @c a.
|
||||
*
|
||||
* Use of signed int mean that this is only valid for values in range [0, 31].
|
||||
* Use of signed int means that this is only valid for values in range [0, 31].
|
||||
*/
|
||||
static ASTCENC_SIMD_INLINE vint4 two_to_the_n(vint4 a)
|
||||
{
|
||||
|
|
|
@ -89,7 +89,8 @@ struct vfloat8
|
|||
/**
|
||||
* @brief Construct from an existing SIMD register.
|
||||
*/
|
||||
ASTCENC_SIMD_INLINE explicit vfloat8(__m256 a) {
|
||||
ASTCENC_SIMD_INLINE explicit vfloat8(__m256 a)
|
||||
{
|
||||
m = a;
|
||||
}
|
||||
|
||||
|
|
|
@ -361,6 +361,23 @@ static inline int popcount(uint64_t v)
|
|||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Apply signed bit transfer.
|
||||
*
|
||||
* @param input0 The first encoded endpoint.
|
||||
* @param input1 The second encoded endpoint.
|
||||
*/
|
||||
static ASTCENC_SIMD_INLINE void bit_transfer_signed(
|
||||
vint4& input0,
|
||||
vint4& input1
|
||||
) {
|
||||
input1 = lsr<1>(input1) | (input0 & 0x80);
|
||||
input0 = lsr<1>(input0) & 0x3F;
|
||||
|
||||
vmask4 mask = (input0 & 0x20) != vint4::zero();
|
||||
input0 = select(input0, input0 - 0x40, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Debug function to print a vector of ints.
|
||||
*/
|
||||
|
|
|
@ -106,7 +106,7 @@ struct vfloat4
|
|||
*/
|
||||
template <int l> ASTCENC_SIMD_INLINE void set_lane(float a)
|
||||
{
|
||||
m = vld1q_lane_f32(&a, m, l);
|
||||
m = vsetq_lane_f32(a, m, l);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +122,7 @@ struct vfloat4
|
|||
*/
|
||||
static ASTCENC_SIMD_INLINE vfloat4 load1(const float* p)
|
||||
{
|
||||
return vfloat4(vdupq_n_f32(*p));
|
||||
return vfloat4(vld1q_dup_f32(p));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,9 +202,8 @@ struct vint4
|
|||
*/
|
||||
ASTCENC_SIMD_INLINE explicit vint4(const uint8_t *p)
|
||||
{
|
||||
uint32x2_t t8 {};
|
||||
// Cast is safe - NEON loads are allowed to be unaligned
|
||||
t8 = vld1_lane_u32(reinterpret_cast<const uint32_t*>(p), t8, 0);
|
||||
uint32x2_t t8 = vld1_dup_u32(reinterpret_cast<const uint32_t*>(p));
|
||||
uint16x4_t t16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(t8)));
|
||||
m = vreinterpretq_s32_u32(vmovl_u16(t16));
|
||||
}
|
||||
|
@ -251,7 +250,7 @@ struct vint4
|
|||
*/
|
||||
template <int l> ASTCENC_SIMD_INLINE void set_lane(int a)
|
||||
{
|
||||
m = vld1q_lane_s32(&a, m, l);
|
||||
m = vsetq_lane_s32(a, m, l);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1039,18 +1038,18 @@ ASTCENC_SIMD_INLINE void store_lanes_masked(int* base, vint4 data, vmask4 mask)
|
|||
{
|
||||
store(data, base);
|
||||
}
|
||||
else if(mask.lane<2>())
|
||||
else if (mask.lane<2>())
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
base[1] = data.lane<1>();
|
||||
base[2] = data.lane<2>();
|
||||
}
|
||||
else if(mask.lane<1>())
|
||||
else if (mask.lane<1>())
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
base[1] = data.lane<1>();
|
||||
}
|
||||
else if(mask.lane<0>())
|
||||
else if (mask.lane<0>())
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
}
|
||||
|
|
|
@ -1149,18 +1149,18 @@ ASTCENC_SIMD_INLINE void store_lanes_masked(int* base, vint4 data, vmask4 mask)
|
|||
{
|
||||
store(data, base);
|
||||
}
|
||||
else if(mask.m[2])
|
||||
else if (mask.m[2])
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
base[1] = data.lane<1>();
|
||||
base[2] = data.lane<2>();
|
||||
}
|
||||
else if(mask.m[1])
|
||||
else if (mask.m[1])
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
base[1] = data.lane<1>();
|
||||
}
|
||||
else if(mask.m[0])
|
||||
else if (mask.m[0])
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
}
|
||||
|
|
|
@ -1206,18 +1206,18 @@ ASTCENC_SIMD_INLINE void store_lanes_masked(int* base, vint4 data, vmask4 mask)
|
|||
{
|
||||
store(data, base);
|
||||
}
|
||||
else if(mask.lane<2>() != 0.0f)
|
||||
else if (mask.lane<2>() != 0.0f)
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
base[1] = data.lane<1>();
|
||||
base[2] = data.lane<2>();
|
||||
}
|
||||
else if(mask.lane<1>() != 0.0f)
|
||||
else if (mask.lane<1>() != 0.0f)
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
base[1] = data.lane<1>();
|
||||
}
|
||||
else if(mask.lane<0>() != 0.0f)
|
||||
else if (mask.lane<0>() != 0.0f)
|
||||
{
|
||||
base[0] = data.lane<0>();
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ static void compute_lowest_and_highest_weight(
|
|||
vfloat cut_high_weight_err = vfloat::zero();
|
||||
vfloat offset = loada(offsets + sp);
|
||||
|
||||
for (unsigned int j = 0; j < weight_count; ++j)
|
||||
for (unsigned int j = 0; j < weight_count; j++)
|
||||
{
|
||||
vfloat sval = load1(dec_weight_ideal_value + j) * rcp_stepsize - offset;
|
||||
vfloat svalrte = round(sval);
|
||||
|
@ -287,25 +287,25 @@ static void compute_angular_endpoints_for_quant_levels(
|
|||
// Check best error against record N
|
||||
vfloat4 best_result = best_results[idx_span];
|
||||
vfloat4 new_result = vfloat4(error[i], i_flt, 0.0f, 0.0f);
|
||||
vmask4 mask1(best_result.lane<0>() > error[i]);
|
||||
best_results[idx_span] = select(best_result, new_result, mask1);
|
||||
vmask4 mask = vfloat4(best_result.lane<0>()) > vfloat4(error[i]);
|
||||
best_results[idx_span] = select(best_result, new_result, mask);
|
||||
|
||||
// Check best error against record N-1 with either cut low or cut high
|
||||
best_result = best_results[idx_span - 1];
|
||||
|
||||
new_result = vfloat4(error_cut_low, i_flt, 1.0f, 0.0f);
|
||||
vmask4 mask2(best_result.lane<0>() > error_cut_low);
|
||||
best_result = select(best_result, new_result, mask2);
|
||||
mask = vfloat4(best_result.lane<0>()) > vfloat4(error_cut_low);
|
||||
best_result = select(best_result, new_result, mask);
|
||||
|
||||
new_result = vfloat4(error_cut_high, i_flt, 0.0f, 0.0f);
|
||||
vmask4 mask3(best_result.lane<0>() > error_cut_high);
|
||||
best_results[idx_span - 1] = select(best_result, new_result, mask3);
|
||||
mask = vfloat4(best_result.lane<0>()) > vfloat4(error_cut_high);
|
||||
best_results[idx_span - 1] = select(best_result, new_result, mask);
|
||||
|
||||
// Check best error against record N-2 with both cut low and high
|
||||
best_result = best_results[idx_span - 2];
|
||||
new_result = vfloat4(error_cut_low_high, i_flt, 1.0f, 0.0f);
|
||||
vmask4 mask4(best_result.lane<0>() > error_cut_low_high);
|
||||
best_results[idx_span - 2] = select(best_result, new_result, mask4);
|
||||
mask = vfloat4(best_result.lane<0>()) > vfloat4(error_cut_low_high);
|
||||
best_results[idx_span - 2] = select(best_result, new_result, mask);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= max_quant_level; i++)
|
||||
|
@ -333,158 +333,8 @@ static void compute_angular_endpoints_for_quant_levels(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given step size compute the lowest and highest weight, variant for low weight count.
|
||||
*
|
||||
* Compute the lowest and highest weight that results from quantizing using the given stepsize and
|
||||
* offset, and then compute the resulting error. The cut errors indicate the error that results from
|
||||
* forcing samples that should have had one weight value one step up or down.
|
||||
*
|
||||
* @param weight_count The number of (decimated) weights.
|
||||
* @param dec_weight_quant_uvalue The decimated and quantized weight values.
|
||||
* @param max_angular_steps The maximum number of steps to be tested.
|
||||
* @param max_quant_steps The maximum quantization level to be tested.
|
||||
* @param offsets The angular offsets array.
|
||||
* @param[out] lowest_weight Per angular step, the lowest weight.
|
||||
* @param[out] weight_span Per angular step, the span between lowest and highest weight.
|
||||
* @param[out] error Per angular step, the error.
|
||||
*/
|
||||
static void compute_lowest_and_highest_weight_lwc(
|
||||
unsigned int weight_count,
|
||||
const float* dec_weight_quant_uvalue,
|
||||
unsigned int max_angular_steps,
|
||||
unsigned int max_quant_steps,
|
||||
const float* offsets,
|
||||
float* lowest_weight,
|
||||
int* weight_span,
|
||||
float* error
|
||||
) {
|
||||
promise(weight_count > 0);
|
||||
promise(max_angular_steps > 0);
|
||||
|
||||
vfloat rcp_stepsize = vfloat::lane_id() + vfloat(1.0f);
|
||||
|
||||
// Arrays are ANGULAR_STEPS long, so always safe to run full vectors
|
||||
for (unsigned int sp = 0; sp < max_angular_steps; sp += ASTCENC_SIMD_WIDTH)
|
||||
{
|
||||
vfloat minidx(128.0f);
|
||||
vfloat maxidx(-128.0f);
|
||||
vfloat errval = vfloat::zero();
|
||||
vfloat offset = loada(offsets + sp);
|
||||
|
||||
for (unsigned int j = 0; j < weight_count; ++j)
|
||||
{
|
||||
vfloat sval = load1(dec_weight_quant_uvalue + j) * rcp_stepsize - offset;
|
||||
vfloat svalrte = round(sval);
|
||||
vfloat diff = sval - svalrte;
|
||||
errval += diff * diff;
|
||||
|
||||
// Compute min and max quantized weight spans for each step
|
||||
minidx = min(minidx, svalrte);
|
||||
maxidx = max(maxidx, svalrte);
|
||||
}
|
||||
|
||||
// Write out min weight and weight span; clamp span to a usable range
|
||||
vint span = float_to_int(maxidx - minidx + vfloat(1.0f));
|
||||
span = min(span, vint(max_quant_steps + 3));
|
||||
span = max(span, vint(2));
|
||||
storea(minidx, lowest_weight + sp);
|
||||
storea(span, weight_span + sp);
|
||||
|
||||
// The cut_(lowest/highest)_weight_error indicate the error that results from
|
||||
// forcing samples that should have had the weight value one step (up/down).
|
||||
vfloat ssize = 1.0f / rcp_stepsize;
|
||||
vfloat errscale = ssize * ssize;
|
||||
storea(errval * errscale, error + sp);
|
||||
|
||||
rcp_stepsize = rcp_stepsize + vfloat(ASTCENC_SIMD_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The main function for the angular algorithm, variant for low weight count.
|
||||
*
|
||||
* @param weight_count The number of (decimated) weights.
|
||||
* @param dec_weight_ideal_value The ideal decimated unquantized weight values.
|
||||
* @param max_quant_level The maximum quantization level to be tested.
|
||||
* @param[out] low_value Per angular step, the lowest weight value.
|
||||
* @param[out] high_value Per angular step, the highest weight value.
|
||||
*/
|
||||
static void compute_angular_endpoints_for_quant_levels_lwc(
|
||||
unsigned int weight_count,
|
||||
const float* dec_weight_ideal_value,
|
||||
unsigned int max_quant_level,
|
||||
float low_value[TUNE_MAX_ANGULAR_QUANT + 1],
|
||||
float high_value[TUNE_MAX_ANGULAR_QUANT + 1]
|
||||
) {
|
||||
unsigned int max_quant_steps = steps_for_quant_level[max_quant_level];
|
||||
unsigned int max_angular_steps = steps_for_quant_level[max_quant_level];
|
||||
|
||||
alignas(ASTCENC_VECALIGN) float angular_offsets[ANGULAR_STEPS];
|
||||
alignas(ASTCENC_VECALIGN) float lowest_weight[ANGULAR_STEPS];
|
||||
alignas(ASTCENC_VECALIGN) int32_t weight_span[ANGULAR_STEPS];
|
||||
alignas(ASTCENC_VECALIGN) float error[ANGULAR_STEPS];
|
||||
|
||||
compute_angular_offsets(weight_count, dec_weight_ideal_value,
|
||||
max_angular_steps, angular_offsets);
|
||||
|
||||
|
||||
compute_lowest_and_highest_weight_lwc(weight_count, dec_weight_ideal_value,
|
||||
max_angular_steps, max_quant_steps,
|
||||
angular_offsets, lowest_weight, weight_span, error);
|
||||
|
||||
// For each quantization level, find the best error terms. Use packed vectors so data-dependent
|
||||
// branches can become selects. This involves some integer to float casts, but the values are
|
||||
// small enough so they never round the wrong way.
|
||||
vfloat4 best_results[36];
|
||||
|
||||
// Initialize the array to some safe defaults
|
||||
promise(max_quant_steps > 0);
|
||||
for (unsigned int i = 0; i < (max_quant_steps + 4); i++)
|
||||
{
|
||||
best_results[i] = vfloat4(ERROR_CALC_DEFAULT, -1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
promise(max_angular_steps > 0);
|
||||
for (unsigned int i = 0; i < max_angular_steps; i++)
|
||||
{
|
||||
int idx_span = weight_span[i];
|
||||
|
||||
// Check best error against record N
|
||||
vfloat4 current_best = best_results[idx_span];
|
||||
vfloat4 candidate = vfloat4(error[i], static_cast<float>(i), 0.0f, 0.0f);
|
||||
vmask4 mask(current_best.lane<0>() > error[i]);
|
||||
best_results[idx_span] = select(current_best, candidate, mask);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= max_quant_level; i++)
|
||||
{
|
||||
unsigned int q = steps_for_quant_level[i];
|
||||
int bsi = static_cast<int>(best_results[q].lane<1>());
|
||||
|
||||
// Did we find anything?
|
||||
#if defined(ASTCENC_DIAGNOSTICS)
|
||||
if ((bsi < 0) && print_once)
|
||||
{
|
||||
print_once = false;
|
||||
printf("INFO: Unable to find low weight encoding within search error limit.\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
bsi = astc::max(0, bsi);
|
||||
|
||||
float lwi = lowest_weight[bsi];
|
||||
float hwi = lwi + static_cast<float>(q) - 1.0f;
|
||||
|
||||
float stepsize = 1.0f / (1.0f + static_cast<float>(bsi));
|
||||
low_value[i] = (angular_offsets[bsi] + lwi) * stepsize;
|
||||
high_value[i] = (angular_offsets[bsi] + hwi) * stepsize;
|
||||
}
|
||||
}
|
||||
|
||||
/* See header for documentation. */
|
||||
void compute_angular_endpoints_1plane(
|
||||
unsigned int tune_low_weight_limit,
|
||||
bool only_always,
|
||||
const block_size_descriptor& bsd,
|
||||
const float* dec_weight_ideal_value,
|
||||
|
@ -521,26 +371,16 @@ void compute_angular_endpoints_1plane(
|
|||
max_precision = max_weight_quant;
|
||||
}
|
||||
|
||||
if (weight_count < tune_low_weight_limit)
|
||||
{
|
||||
compute_angular_endpoints_for_quant_levels_lwc(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS,
|
||||
max_precision, low_values[i], high_values[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
compute_angular_endpoints_for_quant_levels(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS,
|
||||
max_precision, low_values[i], high_values[i]);
|
||||
}
|
||||
compute_angular_endpoints_for_quant_levels(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS,
|
||||
max_precision, low_values[i], high_values[i]);
|
||||
}
|
||||
|
||||
unsigned int max_block_modes = only_always ? bsd.block_mode_count_1plane_always
|
||||
: bsd.block_mode_count_1plane_selected;
|
||||
promise(max_block_modes > 0);
|
||||
for (unsigned int i = 0; i < max_block_modes; ++i)
|
||||
for (unsigned int i = 0; i < max_block_modes; i++)
|
||||
{
|
||||
const block_mode& bm = bsd.block_modes[i];
|
||||
assert(!bm.is_dual_plane);
|
||||
|
@ -563,7 +403,6 @@ void compute_angular_endpoints_1plane(
|
|||
|
||||
/* See header for documentation. */
|
||||
void compute_angular_endpoints_2planes(
|
||||
unsigned int tune_low_weight_limit,
|
||||
const block_size_descriptor& bsd,
|
||||
const float* dec_weight_ideal_value,
|
||||
unsigned int max_weight_quant,
|
||||
|
@ -601,30 +440,15 @@ void compute_angular_endpoints_2planes(
|
|||
max_precision = max_weight_quant;
|
||||
}
|
||||
|
||||
if (weight_count < tune_low_weight_limit)
|
||||
{
|
||||
compute_angular_endpoints_for_quant_levels_lwc(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS,
|
||||
max_precision, low_values1[i], high_values1[i]);
|
||||
compute_angular_endpoints_for_quant_levels(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS,
|
||||
max_precision, low_values1[i], high_values1[i]);
|
||||
|
||||
compute_angular_endpoints_for_quant_levels_lwc(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET,
|
||||
max_precision, low_values2[i], high_values2[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
compute_angular_endpoints_for_quant_levels(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS,
|
||||
max_precision, low_values1[i], high_values1[i]);
|
||||
|
||||
compute_angular_endpoints_for_quant_levels(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET,
|
||||
max_precision, low_values2[i], high_values2[i]);
|
||||
}
|
||||
compute_angular_endpoints_for_quant_levels(
|
||||
weight_count,
|
||||
dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET,
|
||||
max_precision, low_values2[i], high_values2[i]);
|
||||
}
|
||||
|
||||
unsigned int start = bsd.block_mode_count_1plane_selected;
|
||||
|
|
|
@ -24,9 +24,8 @@
|
|||
#define _ 0 // Using _ to indicate an entry that will not be used.
|
||||
|
||||
const quant_and_transfer_table quant_and_xfer_tables[12] {
|
||||
// Quantization method 0, range 0..1
|
||||
// QUANT2, range 0..1
|
||||
{
|
||||
QUANT_2,
|
||||
{0, 64},
|
||||
{0, 1},
|
||||
{0, 64},
|
||||
|
@ -34,9 +33,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
|
||||
0x4000}
|
||||
},
|
||||
// Quantization method 1, range 0..2
|
||||
// QUANT_3, range 0..2
|
||||
{
|
||||
QUANT_3,
|
||||
{0, 32, 64},
|
||||
{0, 1, 2},
|
||||
{0, 32, 64},
|
||||
|
@ -44,19 +42,17 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,_,0x4000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
|
||||
_,_,_,_,0x4020}
|
||||
},
|
||||
// Quantization method 2, range 0..3
|
||||
// QUANT_4, range 0..3
|
||||
{
|
||||
QUANT_4,
|
||||
{0, 21, 43, 64},
|
||||
{0, 1, 2, 3},
|
||||
{0, 21, 43, 64},
|
||||
{0, 21, 43, 64},
|
||||
{0x1500,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x2b00,_,_,_,_,
|
||||
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x4015,_,_,_,_,_,_,_,_,_,_,_,_,
|
||||
_,_,_,_,_,_,_,_,0x402b}
|
||||
},
|
||||
// Quantization method 3, range 0..4
|
||||
//QUANT_5, range 0..4
|
||||
{
|
||||
QUANT_5,
|
||||
{0, 16, 32, 48, 64},
|
||||
{0, 1, 2, 3, 4},
|
||||
{0, 16, 32, 48, 64},
|
||||
|
@ -64,9 +60,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,_,_,_,_,_,0x3010,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x4020,_,_,_,
|
||||
_,_,_,_,_,_,_,_,_,_,_,_,0x4030}
|
||||
},
|
||||
// Quantization method 4, range 0..5
|
||||
// QUANT_6, range 0..5
|
||||
{
|
||||
QUANT_6,
|
||||
{0, 12, 25, 39, 52, 64},
|
||||
{0, 2, 4, 5, 3, 1},
|
||||
{0, 64, 12, 52, 25, 39},
|
||||
|
@ -74,9 +69,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
0x270c,_,_,_,_,_,_,_,_,_,_,_,_,_,0x3419,_,_,_,_,_,_,_,_,_,_,
|
||||
_,_,0x4027,_,_,_,_,_,_,_,_,_,_,_,0x4034}
|
||||
},
|
||||
// Quantization method 5, range 0..7
|
||||
// QUANT_8, range 0..7
|
||||
{
|
||||
QUANT_8,
|
||||
{0, 9, 18, 27, 37, 46, 55, 64},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7},
|
||||
{0, 9, 18, 27, 37, 46, 55, 64},
|
||||
|
@ -84,9 +78,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,_,_,_,_,_,0x2512,_,_,_,_,_,_,_,_,_,0x2e1b,_,_,_,_,_,_,_,_,
|
||||
0x3725,_,_,_,_,_,_,_,_,0x402e,_,_,_,_,_,_,_,_,0x4037}
|
||||
},
|
||||
// Quantization method 6, range 0..9
|
||||
// QUANT_10, range 0..9
|
||||
{
|
||||
QUANT_10,
|
||||
{0, 7, 14, 21, 28, 36, 43, 50, 57, 64},
|
||||
{0, 2, 4, 6, 8, 9, 7, 5, 3, 1},
|
||||
{0, 64, 7, 57, 14, 50, 21, 43, 28, 36},
|
||||
|
@ -95,9 +88,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,0x3224,_,_,_,_,_,_,0x392b,_,_,_,_,_,_,0x4032,_,_,_,_,_,
|
||||
_,0x4039}
|
||||
},
|
||||
// Quantization method 7, range 0..11
|
||||
// QUANT_12, range 0..11
|
||||
{
|
||||
QUANT_12,
|
||||
{0, 5, 11, 17, 23, 28, 36, 41, 47, 53, 59, 64},
|
||||
{0, 4, 8, 2, 6, 10, 11, 7, 3, 9, 5, 1},
|
||||
{0, 64, 17, 47, 5, 59, 23, 41, 11, 53, 28, 36},
|
||||
|
@ -106,9 +98,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
0x291c,_,_,_,_,0x2f24,_,_,_,_,_,0x3529,_,_,_,_,_,
|
||||
0x3b2f,_,_,_,_,_,0x4035,_,_,_,_,0x403b}
|
||||
},
|
||||
// Quantization method 8, range 0..15
|
||||
// QUANT_16, range 0..15
|
||||
{
|
||||
QUANT_16,
|
||||
{0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64},
|
||||
|
@ -117,9 +108,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,0x271d,_,_,_,0x2b23,_,_,_,0x2f27,_,_,_,0x342b,_,_,_,
|
||||
_,0x382f,_,_,_,0x3c34,_,_,_,0x4038,_,_,_,0x403c}
|
||||
},
|
||||
// Quantization method 9, range 0..19
|
||||
// QUANT_20, range 0..19
|
||||
{
|
||||
QUANT_20,
|
||||
{0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 35, 38, 41, 45, 48, 51, 55, 58, 61, 64},
|
||||
{0, 4, 8, 12, 16, 2, 6, 10, 14, 18, 19, 15, 11, 7, 3, 17, 13, 9, 5, 1},
|
||||
{0, 64, 16, 48, 3, 61, 19, 45, 6, 58, 23, 41, 9, 55, 26, 38, 13, 51, 29, 35},
|
||||
|
@ -129,9 +119,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
0x2d26,_,_,_,0x3029,_,_,0x332d,_,_,0x3730,_,_,_,
|
||||
0x3a33,_,_,0x3d37,_,_,0x403a,_,_,0x403d}
|
||||
},
|
||||
// Quantization method 10, range 0..23
|
||||
// QUANT_24, range 0..23
|
||||
{
|
||||
QUANT_24,
|
||||
{0, 2, 5, 8, 11, 13, 16, 19, 22, 24, 27, 30, 34, 37, 40, 42, 45, 48, 51, 53, 56, 59, 62, 64},
|
||||
{0, 8, 16, 2, 10, 18, 4, 12, 20, 6, 14, 22, 23, 15, 7, 21, 13, 5, 19, 11, 3, 17, 9, 1},
|
||||
{0, 64, 8, 56, 16, 48, 24, 40, 2, 62, 11, 53, 19, 45, 27, 37, 5, 59, 13, 51, 22, 42, 30, 34},
|
||||
|
@ -142,9 +131,8 @@ const quant_and_transfer_table quant_and_xfer_tables[12] {
|
|||
_,_,0x3530,_,0x3833,_,_,0x3b35,_,_,0x3e38,_,_,
|
||||
0x403b,_,0x403e}
|
||||
},
|
||||
// Quantization method 11, range 0..31
|
||||
// QUANT_32, range 0..31
|
||||
{
|
||||
QUANT_32,
|
||||
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
|
||||
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Loader generated by glad 2.0.2 on Thu Nov 10 09:27:21 2022
|
||||
* Loader generated by glad 2.0.3 on Fri Jan 20 03:41:44 2023
|
||||
*
|
||||
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
||||
*
|
||||
|
@ -177,7 +177,7 @@ extern "C" {
|
|||
#define GLAD_VERSION_MAJOR(version) (version / 10000)
|
||||
#define GLAD_VERSION_MINOR(version) (version % 10000)
|
||||
|
||||
#define GLAD_GENERATOR_VERSION "2.0.2"
|
||||
#define GLAD_GENERATOR_VERSION "2.0.3"
|
||||
|
||||
typedef void (*GLADapiproc)(void);
|
||||
|
||||
|
@ -10603,7 +10603,7 @@ typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DOESPROC)(GLenum target, GLint
|
|||
typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURELEVELSAPPLEPROC)(GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
|
||||
typedef void (GLAD_API_PTR *PFNGLCOVERAGEMASKNVPROC)(GLboolean mask);
|
||||
typedef void (GLAD_API_PTR *PFNGLCOVERAGEOPERATIONNVPROC)(GLenum operation);
|
||||
typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVEXTPROC)(GLenum type, GLsizei count, const GLchar ** strings);
|
||||
typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVEXTPROC)(GLenum type, GLsizei count, const GLchar *const* strings);
|
||||
typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKKHRPROC)(GLDEBUGPROCKHR callback, const void * userParam);
|
||||
typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLKHRPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
|
||||
typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTKHRPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
|
||||
|
|
|
@ -139,13 +139,21 @@ information on what to include when reporting a bug.
|
|||
- Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427)
|
||||
- Added `GLFW_MOUSE_PASSTHROUGH` window hint for letting mouse input pass
|
||||
through the window (#1236,#1568)
|
||||
- Added `GLFW_CURSOR_CAPTURED` cursor mode to confine the cursor to the window
|
||||
content area (#58)
|
||||
- Added `GLFW_POSITION_X` and `GLFW_POSITION_Y` window hints for initial position
|
||||
(#1603,#1747)
|
||||
- Added `GLFW_ANY_POSITION` hint value for letting the window manager choose (#1603,#1747)
|
||||
- Added `GLFW_PLATFORM_UNAVAILABLE` error for platform detection failures (#1958)
|
||||
- Added `GLFW_FEATURE_UNAVAILABLE` error for platform limitations (#1692)
|
||||
- Added `GLFW_FEATURE_UNIMPLEMENTED` error for incomplete backends (#1692)
|
||||
- Added `GLFW_WAYLAND_APP_ID` window hint string for Wayland app\_id selection
|
||||
(#2121,#2122)
|
||||
- Added `GLFW_ANGLE_PLATFORM_TYPE` init hint and `GLFW_ANGLE_PLATFORM_TYPE_*`
|
||||
values to select ANGLE backend (#1380)
|
||||
- Added `GLFW_X11_XCB_VULKAN_SURFACE` init hint for selecting X11 Vulkan
|
||||
surface extension (#1793)
|
||||
- Added `GLFW_NATIVE_INCLUDE_NONE` for disabling inclusion of native headers (#1348)
|
||||
- Added `GLFW_BUILD_WIN32` CMake option for enabling Win32 support (#1958)
|
||||
- Added `GLFW_BUILD_COCOA` CMake option for enabling Cocoa support (#1958)
|
||||
- Added `GLFW_BUILD_X11` CMake option for enabling X11 support (#1958)
|
||||
|
@ -172,9 +180,13 @@ information on what to include when reporting a bug.
|
|||
- Bugfix: Gamepad mapping updates could spam `GLFW_INVALID_VALUE` due to
|
||||
incompatible controllers sharing hardware ID (#1763)
|
||||
- Bugfix: Native access functions for context handles did not check that the API matched
|
||||
- Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization
|
||||
- Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization
|
||||
- Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092)
|
||||
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
|
||||
to the window menu
|
||||
- [Win32] Added a version info resource to the GLFW DLL
|
||||
- [Win32] Made hidden helper window use its own window class
|
||||
- [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are
|
||||
opaque (#1512)
|
||||
- [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused
|
||||
|
@ -205,12 +217,25 @@ information on what to include when reporting a bug.
|
|||
- [Win32] Bugfix: Content scale queries could fail silently (#1615)
|
||||
- [Win32] Bugfix: Content scales could have garbage values if monitor was recently
|
||||
disconnected (#1615)
|
||||
- [Win32] Bugfix: A window created maximized and undecorated would cover the whole
|
||||
monitor (#1806)
|
||||
- [Win32] Bugfix: The default restored window position was lost when creating a maximized
|
||||
window
|
||||
- [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible
|
||||
- [Win32] Bugfix: `Alt+PrtSc` would emit `GLFW_KEY_UNKNOWN` and a different
|
||||
scancode than `PrtSc` (#1993)
|
||||
- [Win32] Bugfix: `GLFW_KEY_PAUSE` scancode from `glfwGetKeyScancode` did not
|
||||
match event scancode (#1993)
|
||||
- [Win32] Bugfix: Instance-local operations used executable instance (#469,#1296,#1395)
|
||||
- [Win32] Bugfix: The OSMesa library was not unloaded on termination
|
||||
- [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050)
|
||||
- [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
|
||||
- [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
|
||||
- [Cocoa] Moved main menu creation to GLFW initialization time (#1649)
|
||||
- [Cocoa] Changed `EGLNativeWindowType` from `NSView` to `CALayer` (#1169)
|
||||
- [Cocoa] Changed F13 key to report Print Screen for cross-platform consistency
|
||||
(#1786)
|
||||
- [Cocoa] Disabled macOS fullscreen when `GLFW_RESIZABLE` is false
|
||||
- [Cocoa] Removed dependency on the CoreVideo framework
|
||||
- [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553)
|
||||
- [Cocoa] Bugfix: Window remained on screen after destruction until event poll
|
||||
|
@ -234,6 +259,16 @@ information on what to include when reporting a bug.
|
|||
- [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for
|
||||
a fraction of a second (#1962)
|
||||
- [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980)
|
||||
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
|
||||
- [Cocoa] Bugfix: A connected Apple AirPlay would emit a useless error (#1791)
|
||||
- [Cocoa] Bugfix: The EGL and OSMesa libraries were not unloaded on termination
|
||||
- [Cocoa] Bugfix: `GLFW_MAXIMIZED` was always true when `GLFW_RESIZABLE` was false
|
||||
- [Cocoa] Bugfix: Changing `GLFW_DECORATED` in macOS fullscreen would abort
|
||||
application (#1886)
|
||||
- [Cocoa] Bugfix: Setting a monitor from macOS fullscreen would abort
|
||||
application (#2110)
|
||||
- [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle
|
||||
subdirectory (#2113,#2120)
|
||||
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
|
||||
- [X11] Bugfix: Key names were not updated when the keyboard layout changed
|
||||
(#1462,#1528)
|
||||
|
@ -265,8 +300,23 @@ information on what to include when reporting a bug.
|
|||
- [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on
|
||||
undefined behavior (#1986)
|
||||
- [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
|
||||
- [X11] Bugfix: Waiting for events would fail if file descriptor was too large
|
||||
(#2024)
|
||||
- [X11] Bugfix: Joystick events could lead to busy-waiting (#1872)
|
||||
- [X11] Bugfix: `glfwWaitEvents*` did not continue for joystick events
|
||||
- [X11] Bugfix: `glfwPostEmptyEvent` could be ignored due to race condition
|
||||
(#379,#1281,#1285,#2033)
|
||||
- [X11] Bugfix: Dynamic loading on NetBSD failed due to soname differences
|
||||
- [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
|
||||
- [X11] Bugfix: The OSMesa libray was not unloaded on termination
|
||||
- [X11] Bugfix: A malformed response during selection transfer could cause a segfault
|
||||
- [X11] Bugfix: Some calls would reset Xlib to the default error handler (#2108)
|
||||
- [Wayland] Added dynamic loading of all Wayland libraries
|
||||
- [Wayland] Added support for key names via xkbcommon
|
||||
- [Wayland] Added support for file path drop events (#2040)
|
||||
- [Wayland] Added support for more human-readable monitor names where available
|
||||
- [Wayland] Disabled alpha channel for opaque windows on systems lacking
|
||||
`EGL_EXT_present_opaque` (#1895)
|
||||
- [Wayland] Removed support for `wl_shell` (#1443)
|
||||
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
|
||||
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
|
||||
|
@ -289,8 +339,52 @@ information on what to include when reporting a bug.
|
|||
- [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
|
||||
- [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
|
||||
- [Wayland] Bugfix: Text input did not repeat along with key repeat
|
||||
- [Wayland] Bugfix: `glfwPostEmptyEvent` sometimes had no effect (#1520,#1521)
|
||||
- [Wayland] Bugfix: `glfwSetClipboardString` would fail if set to result of
|
||||
`glfwGetClipboardString`
|
||||
- [Wayland] Bugfix: Data source creation error would cause double free at termination
|
||||
- [Wayland] Bugfix: Partial writes of clipboard string would cause beginning to repeat
|
||||
- [Wayland] Bugfix: Some errors would cause clipboard string transfer to hang
|
||||
- [Wayland] Bugfix: Drag and drop data was misinterpreted as clipboard string
|
||||
- [Wayland] Bugfix: MIME type matching was not performed for clipboard string
|
||||
- [Wayland] Bugfix: The OSMesa library was not unloaded on termination
|
||||
- [Wayland] Bugfix: `glfwCreateWindow` could emit `GLFW_FEATURE_UNAVAILABLE`
|
||||
- [Wayland] Bugfix: Lock key modifier bits were only set when lock keys were pressed
|
||||
- [Wayland] Bugfix: A window leaving full screen mode would be iconified (#1995)
|
||||
- [Wayland] Bugfix: A window leaving full screen mode ignored its desired size
|
||||
- [Wayland] Bugfix: `glfwSetWindowMonitor` did not update windowed mode size
|
||||
- [Wayland] Bugfix: `glfwRestoreWindow` would make a full screen window windowed
|
||||
- [Wayland] Bugfix: A window maximized or restored by the user would enter an
|
||||
inconsistent state
|
||||
- [Wayland] Bugfix: Window maximization events were not emitted
|
||||
- [Wayland] Bugfix: `glfwRestoreWindow` assumed it was always in windowed mode
|
||||
- [Wayland] Bugfix: `glfwSetWindowSize` would resize a full screen window
|
||||
- [Wayland] Bugfix: A window content scale event would be emitted every time
|
||||
the window resized
|
||||
- [Wayland] Bugfix: If `glfwInit` failed it would close stdin
|
||||
- [Wayland] Bugfix: Manual resizing with fallback decorations behaved erratically
|
||||
(#1991,#2115,#2127)
|
||||
- [Wayland] Bugfix: Size limits included frame size for fallback decorations
|
||||
- [Wayland] Bugfix: Updating `GLFW_DECORATED` had no effect on server-side
|
||||
decorations
|
||||
- [Wayland] Bugfix: A monitor would be reported as connected again if its scale
|
||||
changed
|
||||
- [Wayland] Bugfix: `glfwTerminate` would segfault if any monitor had changed
|
||||
scale
|
||||
- [Wayland] Bugfix: Window content scale events were not emitted when monitor
|
||||
scale changed
|
||||
- [Wayland] Bugfix: `glfwSetWindowAspectRatio` reported an error instead of
|
||||
applying the specified ratio
|
||||
- [Wayland] Bugfix: `GLFW_MAXIMIZED` window hint had no effect
|
||||
- [Wayland] Bugfix: `glfwRestoreWindow` had no effect before first show
|
||||
- [Wayland] Bugfix: Hiding and then showing a window caused program abort on
|
||||
wlroots compositors (#1268)
|
||||
- [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG
|
||||
decorations
|
||||
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
|
||||
- [POSIX] Removed use of deprecated function `gettimeofday`
|
||||
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
|
||||
- [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043)
|
||||
- [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072)
|
||||
- [NSGL] Removed enforcement of forward-compatible flag for core contexts
|
||||
- [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer
|
||||
|
@ -302,7 +396,10 @@ information on what to include when reporting a bug.
|
|||
(#442)
|
||||
- [EGL] Added ANGLE backend selection via `EGL_ANGLE_platform_angle` extension
|
||||
(#1380)
|
||||
[EGL] Added loading of glvnd `libOpenGL.so.0` where available for OpenGL
|
||||
- [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
|
||||
- [GLX] Added loading of glvnd `libGLX.so.0` where available
|
||||
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
|
||||
|
||||
|
||||
## Contact
|
||||
|
|
|
@ -262,13 +262,12 @@ extern "C" {
|
|||
/* We are building GLFW as a Win32 DLL */
|
||||
#define GLFWAPI __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(GLFW_DLL)
|
||||
/* We are calling GLFW as a Win32 DLL */
|
||||
/* We are calling a GLFW Win32 DLL */
|
||||
#define GLFWAPI __declspec(dllimport)
|
||||
#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
|
||||
/* We are building GLFW as a shared / dynamic library */
|
||||
/* We are building GLFW as a Unix shared library */
|
||||
#define GLFWAPI __attribute__((visibility("default")))
|
||||
#else
|
||||
/* We are building or calling GLFW as a static library */
|
||||
#define GLFWAPI
|
||||
#endif
|
||||
|
||||
|
@ -928,6 +927,18 @@ extern "C" {
|
|||
*/
|
||||
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
||||
|
||||
/*! @brief Initial position x-coordinate window hint.
|
||||
*
|
||||
* Initial position x-coordinate [window hint](@ref GLFW_POSITION_X).
|
||||
*/
|
||||
#define GLFW_POSITION_X 0x0002000E
|
||||
|
||||
/*! @brief Initial position y-coordinate window hint.
|
||||
*
|
||||
* Initial position y-coordinate [window hint](@ref GLFW_POSITION_Y).
|
||||
*/
|
||||
#define GLFW_POSITION_Y 0x0002000F
|
||||
|
||||
/*! @brief Framebuffer bit depth hint.
|
||||
*
|
||||
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
||||
|
@ -1106,6 +1117,12 @@ extern "C" {
|
|||
*/
|
||||
#define GLFW_X11_INSTANCE_NAME 0x00024002
|
||||
#define GLFW_WIN32_KEYBOARD_MENU 0x00025001
|
||||
/*! @brief Wayland specific
|
||||
* [window hint](@ref GLFW_WAYLAND_APP_ID_hint).
|
||||
*
|
||||
* Allows specification of the Wayland app_id.
|
||||
*/
|
||||
#define GLFW_WAYLAND_APP_ID 0x00026001
|
||||
/*! @} */
|
||||
|
||||
#define GLFW_NO_API 0
|
||||
|
@ -1129,6 +1146,7 @@ extern "C" {
|
|||
#define GLFW_CURSOR_NORMAL 0x00034001
|
||||
#define GLFW_CURSOR_HIDDEN 0x00034002
|
||||
#define GLFW_CURSOR_DISABLED 0x00034003
|
||||
#define GLFW_CURSOR_CAPTURED 0x00034004
|
||||
|
||||
#define GLFW_ANY_RELEASE_BEHAVIOR 0
|
||||
#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
|
||||
|
@ -1146,6 +1164,8 @@ extern "C" {
|
|||
#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007
|
||||
#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008
|
||||
|
||||
#define GLFW_ANY_POSITION 0x80000000
|
||||
|
||||
/*! @defgroup shapes Standard cursor shapes
|
||||
* @brief Standard system cursor shapes.
|
||||
*
|
||||
|
@ -2815,11 +2835,11 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
|
|||
* @param[in] monitor The monitor whose gamma ramp to set.
|
||||
* @param[in] gamma The desired exponent.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
|
||||
* @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland Gamma handling is a privileged protocol, this function
|
||||
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
|
||||
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -2839,11 +2859,11 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
|
|||
* @return The current gamma ramp, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
|
||||
* and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland Gamma handling is a privileged protocol, this function
|
||||
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while
|
||||
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
|
||||
* returning `NULL`.
|
||||
*
|
||||
* @pointer_lifetime The returned structure and its arrays are allocated and
|
||||
|
@ -2878,8 +2898,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
|
|||
* @param[in] monitor The monitor whose gamma ramp to set.
|
||||
* @param[in] ramp The gamma ramp to use.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
|
||||
* and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark The size of the specified gamma ramp should match the size of the
|
||||
* current ramp for that monitor.
|
||||
|
@ -2887,7 +2907,7 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
|
|||
* @remark @win32 The gamma ramp size must be 256.
|
||||
*
|
||||
* @remark @wayland Gamma handling is a privileged protocol, this function
|
||||
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
|
||||
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @pointer_lifetime The specified gamma ramp is copied before this function
|
||||
* returns.
|
||||
|
@ -3030,10 +3050,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||
* OpenGL or OpenGL ES context.
|
||||
*
|
||||
* By default, newly created windows use the placement recommended by the
|
||||
* window system. To create the window at a specific position, make it
|
||||
* initially invisible using the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window
|
||||
* hint, set its [position](@ref window_pos) and then [show](@ref window_hide)
|
||||
* it.
|
||||
* window system. To create the window at a specific position, set the @ref
|
||||
* GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints before creation. To
|
||||
* restore the default behavior, set either or both hints back to
|
||||
* `GLFW_ANY_POSITION`.
|
||||
*
|
||||
* As long as at least one full screen window is not iconified, the screensaver
|
||||
* is prohibited from starting.
|
||||
|
@ -3258,7 +3278,8 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
|||
* count is zero.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
* GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref
|
||||
* GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @pointer_lifetime The specified image data is copied before this function
|
||||
* returns.
|
||||
|
@ -3671,8 +3692,9 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
|
|||
* previously restored. If the window is already iconified, this function does
|
||||
* nothing.
|
||||
*
|
||||
* If the specified window is a full screen window, the original monitor
|
||||
* resolution is restored until the window is restored.
|
||||
* If the specified window is a full screen window, GLFW restores the original
|
||||
* video mode of the monitor. The window's desired video mode is set again
|
||||
* when the window is restored.
|
||||
*
|
||||
* @param[in] window The window to iconify.
|
||||
*
|
||||
|
@ -3702,8 +3724,8 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
|
|||
* (minimized) or maximized. If the window is already restored, this function
|
||||
* does nothing.
|
||||
*
|
||||
* If the specified window is a full screen window, the resolution chosen for
|
||||
* the window is restored on the selected monitor.
|
||||
* If the specified window is an iconified full screen window, its desired
|
||||
* video mode is set again for its monitor when the window is restored.
|
||||
*
|
||||
* @param[in] window The window to restore.
|
||||
*
|
||||
|
@ -3971,6 +3993,9 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int
|
|||
* errors. However, this function should not fail as long as it is passed
|
||||
* valid arguments and the library has been [initialized](@ref intro_init).
|
||||
*
|
||||
* @remark @wayland The Wayland protocol provides no way to check whether a
|
||||
* window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_attribs
|
||||
|
@ -4005,7 +4030,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
|
|||
* @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref
|
||||
* GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @remark Calling @ref glfwGetWindowAttrib will always return the latest
|
||||
* value, even if that value is ignored by the current mode of the window.
|
||||
|
@ -4556,6 +4582,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||
* - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
|
||||
* and unlimited cursor movement. This is useful for implementing for
|
||||
* example 3D camera controls.
|
||||
* - `GLFW_CURSOR_CAPTURED` makes the cursor visible and confines it to the
|
||||
* content area of the window.
|
||||
*
|
||||
* If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
|
||||
* enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
|
||||
|
@ -4730,8 +4758,7 @@ GLFWAPI int glfwGetKeyScancode(int key);
|
|||
*
|
||||
* This function returns the last state reported for the specified key to the
|
||||
* specified window. The returned state is one of `GLFW_PRESS` or
|
||||
* `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to
|
||||
* the key callback.
|
||||
* `GLFW_RELEASE`. The action `GLFW_REPEAT` is only reported to the key callback.
|
||||
*
|
||||
* If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns
|
||||
* `GLFW_PRESS` the first time you call it for a key that was pressed, even if
|
||||
|
@ -4855,11 +4882,11 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
|||
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
|
||||
* content area.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||
*
|
||||
* @remark @wayland This function will only work when the cursor mode is
|
||||
* `GLFW_CURSOR_DISABLED`, otherwise it will do nothing.
|
||||
* `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
|
@ -4892,8 +4919,8 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
|
|||
* @return The handle of the created cursor, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The specified image data is copied before this function
|
||||
* returns.
|
||||
|
@ -6383,6 +6410,7 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window
|
|||
*/
|
||||
#ifndef GLAPIENTRY
|
||||
#define GLAPIENTRY APIENTRY
|
||||
#define GLFW_GLAPIENTRY_DEFINED
|
||||
#endif
|
||||
|
||||
/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
|
||||
|
|
|
@ -74,6 +74,16 @@ extern "C" {
|
|||
* and which platform-specific headers to include. It is then up your (by
|
||||
* definition platform-specific) code to handle which of these should be
|
||||
* defined.
|
||||
*
|
||||
* If you do not want the platform-specific headers to be included, define
|
||||
* `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header.
|
||||
*
|
||||
* @code
|
||||
* #define GLFW_EXPOSE_NATIVE_WIN32
|
||||
* #define GLFW_EXPOSE_NATIVE_WGL
|
||||
* #define GLFW_NATIVE_INCLUDE_NONE
|
||||
* #include <GLFW/glfw3native.h>
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
|
||||
|
@ -81,44 +91,71 @@ extern "C" {
|
|||
* System headers and types
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||
// example to allow applications to correctly declare a GL_KHR_debug callback)
|
||||
// but windows.h assumes no one will define APIENTRY before it does
|
||||
#if defined(GLFW_APIENTRY_DEFINED)
|
||||
#undef APIENTRY
|
||||
#undef GLFW_APIENTRY_DEFINED
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
//#include <ApplicationServices/ApplicationServices.h>
|
||||
typedef void* id;
|
||||
#endif
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
#if !defined(GLFW_NATIVE_INCLUDE_NONE)
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/* WGL is declared by windows.h */
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/* NSGL is declared by Cocoa.h */
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||
#include <GL/osmesa.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||
* example to allow applications to correctly declare a GL_KHR_debug callback)
|
||||
* but windows.h assumes no one will define APIENTRY before it does
|
||||
*/
|
||||
#if defined(GLFW_APIENTRY_DEFINED)
|
||||
#undef APIENTRY
|
||||
#undef GLFW_APIENTRY_DEFINED
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <objc/objc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/* WGL is declared by windows.h */
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/* NSGL is declared by Cocoa.h */
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
|
||||
* default it also acts as an OpenGL header
|
||||
* However, glx.h will include gl.h, which will define it unconditionally
|
||||
*/
|
||||
#if defined(GLFW_GLAPIENTRY_DEFINED)
|
||||
#undef GLAPIENTRY
|
||||
#undef GLFW_GLAPIENTRY_DEFINED
|
||||
#endif
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
|
||||
* default it also acts as an OpenGL header
|
||||
* However, osmesa.h will include gl.h, which will define it unconditionally
|
||||
*/
|
||||
#if defined(GLFW_GLAPIENTRY_DEFINED)
|
||||
#undef GLAPIENTRY
|
||||
#undef GLFW_GLAPIENTRY_DEFINED
|
||||
#endif
|
||||
#include <GL/osmesa.h>
|
||||
#endif
|
||||
|
||||
#endif /*GLFW_NATIVE_INCLUDE_NONE*/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -227,7 +264,7 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
|
|||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor);
|
||||
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `NSWindow` of the specified window.
|
||||
*
|
||||
|
@ -475,6 +512,9 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
|
|||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @remark Because EGL is initialized on demand, this function will return
|
||||
* `EGL_NO_DISPLAY` until the first context has been created via EGL.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
|
|
|
@ -60,6 +60,7 @@ if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND)
|
|||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c)
|
||||
endif()
|
||||
target_sources(glfw PRIVATE posix_poll.h posix_poll.c)
|
||||
endif()
|
||||
|
||||
if (GLFW_BUILD_WAYLAND)
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
|
||||
#include <sys/param.h> // For MAXPATHLEN
|
||||
|
||||
// Needed for _NSGetProgname
|
||||
|
@ -460,18 +463,26 @@ void* _glfwLoadLocalVulkanLoaderCocoa(void)
|
|||
if (!bundle)
|
||||
return NULL;
|
||||
|
||||
CFURLRef url =
|
||||
CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
|
||||
if (!url)
|
||||
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
|
||||
if (!frameworksUrl)
|
||||
return NULL;
|
||||
|
||||
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
|
||||
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
|
||||
if (!loaderUrl)
|
||||
{
|
||||
CFRelease(frameworksUrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char path[PATH_MAX];
|
||||
void* handle = NULL;
|
||||
|
||||
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
|
||||
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
|
||||
handle = _glfwPlatformLoadModule(path);
|
||||
|
||||
CFRelease(url);
|
||||
CFRelease(loaderUrl);
|
||||
CFRelease(frameworksUrl);
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -676,7 +687,11 @@ void _glfwTerminateCocoa(void)
|
|||
_glfw_free(_glfw.ns.clipboardString);
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateOSMesa();
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#define GLFW_COCOA_JOYSTICK_STATE _GLFWjoystickNS ns;
|
||||
#define GLFW_COCOA_LIBRARY_JOYSTICK_STATE
|
||||
|
||||
#define GLFW_BUILD_COCOA_MAPPINGS
|
||||
|
||||
// Cocoa-specific per-joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickNS
|
||||
|
@ -45,7 +43,7 @@ typedef struct _GLFWjoystickNS
|
|||
|
||||
GLFWbool _glfwInitJoysticksCocoa(void);
|
||||
void _glfwTerminateJoysticksCocoa(void);
|
||||
int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode);
|
||||
GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode);
|
||||
const char* _glfwGetMappingNameCocoa(void);
|
||||
void _glfwUpdateGamepadGUIDCocoa(char* guid);
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -96,8 +98,7 @@ static CFComparisonResult compareElements(const void* fp,
|
|||
//
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
if (!js->present)
|
||||
return;
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
|
||||
for (int i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||
_glfw_free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
|
||||
|
@ -112,7 +113,6 @@ static void closeJoystick(_GLFWjoystick* js)
|
|||
CFRelease(js->ns.hats);
|
||||
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick addition
|
||||
|
@ -289,9 +289,9 @@ static void removeCallback(void* context,
|
|||
{
|
||||
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.joysticks[jid].ns.device == device)
|
||||
if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].ns.device == device)
|
||||
{
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
closeJoystick(&_glfw.joysticks[jid]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -382,7 +382,10 @@ GLFWbool _glfwInitJoysticksCocoa(void)
|
|||
void _glfwTerminateJoysticksCocoa(void)
|
||||
{
|
||||
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
{
|
||||
if (_glfw.joysticks[jid].connected)
|
||||
closeJoystick(&_glfw.joysticks[jid]);
|
||||
}
|
||||
|
||||
if (_glfw.ns.hidManager)
|
||||
{
|
||||
|
@ -392,7 +395,7 @@ void _glfwTerminateJoysticksCocoa(void)
|
|||
}
|
||||
|
||||
|
||||
int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode)
|
||||
GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
if (mode & _GLFW_POLL_AXES)
|
||||
{
|
||||
|
@ -455,7 +458,7 @@ int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode)
|
|||
}
|
||||
}
|
||||
|
||||
return js->present;
|
||||
return js->connected;
|
||||
}
|
||||
|
||||
const char* _glfwGetMappingNameCocoa(void)
|
||||
|
@ -475,3 +478,5 @@ void _glfwUpdateGamepadGUIDCocoa(char* guid)
|
|||
}
|
||||
}
|
||||
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
@ -98,11 +100,7 @@ static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen)
|
|||
IOObjectRelease(it);
|
||||
|
||||
if (!service)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find service port for display");
|
||||
return _glfw_strdup("Display");
|
||||
}
|
||||
|
||||
CFDictionaryRef names =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
|
||||
|
@ -629,3 +627,5 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
|
|||
return monitor->ns.displayID;
|
||||
}
|
||||
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
|
|
|
@ -42,16 +42,15 @@ typedef void* id;
|
|||
#endif
|
||||
|
||||
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||
// SDK versions where one is unavailable or the other deprecated
|
||||
// We use the newer names in code and these macros to handle compatibility
|
||||
// SDK versions where one is unavailable or deprecated.
|
||||
// We use the newer names in code and replace them with the older names if
|
||||
// the base SDK does not provide the newer names.
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
|
||||
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
|
||||
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||
#endif
|
||||
|
||||
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||
// SDK versions where one is unavailable or the other deprecated
|
||||
// We use the newer names in code and these macros to handle compatibility
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||
#define NSEventMaskAny NSAnyEventMask
|
||||
|
@ -70,6 +69,15 @@ typedef void* id;
|
|||
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||
#endif
|
||||
|
||||
// NOTE: Many Cocoa dynamically linked constants have been renamed and we need
|
||||
// to build across SDK versions where one is unavailable or deprecated.
|
||||
// We use the newer names in code and replace them with the older names if
|
||||
// the deployment target is older than the newer names.
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
||||
#define NSPasteboardTypeURL NSURLPboardType
|
||||
#endif
|
||||
|
||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
||||
|
||||
|
@ -206,7 +214,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform);
|
|||
int _glfwInitCocoa(void);
|
||||
void _glfwTerminateCocoa(void);
|
||||
|
||||
int _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyWindowCocoa(_GLFWwindow* window);
|
||||
void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title);
|
||||
void _glfwSetWindowIconCocoa(_GLFWwindow* window, int count, const GLFWimage* images);
|
||||
|
@ -227,12 +235,12 @@ void _glfwHideWindowCocoa(_GLFWwindow* window);
|
|||
void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window);
|
||||
void _glfwFocusWindowCocoa(_GLFWwindow* window);
|
||||
void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
|
||||
int _glfwWindowFocusedCocoa(_GLFWwindow* window);
|
||||
int _glfwWindowIconifiedCocoa(_GLFWwindow* window);
|
||||
int _glfwWindowVisibleCocoa(_GLFWwindow* window);
|
||||
int _glfwWindowMaximizedCocoa(_GLFWwindow* window);
|
||||
int _glfwWindowHoveredCocoa(_GLFWwindow* window);
|
||||
int _glfwFramebufferTransparentCocoa(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window);
|
||||
GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window);
|
||||
void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
@ -253,8 +261,8 @@ void _glfwSetCursorPosCocoa(_GLFWwindow* window, double xpos, double ypos);
|
|||
void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameCocoa(int scancode);
|
||||
int _glfwGetKeyScancodeCocoa(int key);
|
||||
int _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
int _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape);
|
||||
GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape);
|
||||
void _glfwDestroyCursorCocoa(_GLFWcursor* cursor);
|
||||
void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
void _glfwSetClipboardStringCocoa(const char* string);
|
||||
|
@ -265,7 +273,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayCocoa(void);
|
|||
EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window);
|
||||
|
||||
void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions);
|
||||
int _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_COCOA_TIMER)
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
|
||||
|
@ -53,3 +55,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void)
|
|||
return _glfw.timer.ns.frequency;
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_COCOA_TIMER
|
||||
|
||||
|
|
|
@ -28,28 +28,14 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
|
||||
// Returns the style mask corresponding to the window settings
|
||||
//
|
||||
static NSUInteger getStyleMask(_GLFWwindow* window)
|
||||
{
|
||||
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
|
||||
|
||||
if (window->monitor || !window->decorated)
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
else
|
||||
{
|
||||
styleMask |= NSWindowStyleMaskTitled |
|
||||
NSWindowStyleMaskClosable;
|
||||
|
||||
if (window->resizable)
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
return styleMask;
|
||||
}
|
||||
// HACK: This enum value is missing from framework headers on OS X 10.11 despite
|
||||
// having been (according to documentation) added in Mac OS X 10.7
|
||||
#define NSWindowCollectionBehaviorFullScreenNone (1 << 9)
|
||||
|
||||
// Returns whether the cursor is in the content area of the specified window
|
||||
//
|
||||
|
@ -361,9 +347,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||
markedText = [[NSMutableAttributedString alloc] init];
|
||||
|
||||
[self updateTrackingAreas];
|
||||
// NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
|
||||
// on 10.7 without having been deprecated yet
|
||||
[self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
|
||||
[self registerForDraggedTypes:@[NSPasteboardTypeURL]];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -809,11 +793,35 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
|
||||
}
|
||||
else
|
||||
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
|
||||
{
|
||||
if (wndconfig->xpos == GLFW_ANY_POSITION ||
|
||||
wndconfig->ypos == GLFW_ANY_POSITION)
|
||||
{
|
||||
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int xpos = wndconfig->xpos;
|
||||
const int ypos = _glfwTransformYCocoa(wndconfig->ypos + wndconfig->height - 1);
|
||||
contentRect = NSMakeRect(xpos, ypos, wndconfig->width, wndconfig->height);
|
||||
}
|
||||
}
|
||||
|
||||
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
|
||||
|
||||
if (window->monitor || !window->decorated)
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
else
|
||||
{
|
||||
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
|
||||
|
||||
if (window->resizable)
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
window->ns.object = [[GLFWWindow alloc]
|
||||
initWithContentRect:contentRect
|
||||
styleMask:getStyleMask(window)
|
||||
styleMask:styleMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
|
||||
|
@ -827,10 +835,14 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
||||
else
|
||||
{
|
||||
[(NSWindow*) window->ns.object center];
|
||||
_glfw.ns.cascadePoint =
|
||||
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
||||
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
||||
if (wndconfig->xpos == GLFW_ANY_POSITION ||
|
||||
wndconfig->ypos == GLFW_ANY_POSITION)
|
||||
{
|
||||
[(NSWindow*) window->ns.object center];
|
||||
_glfw.ns.cascadePoint =
|
||||
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
||||
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
||||
}
|
||||
|
||||
if (wndconfig->resizable)
|
||||
{
|
||||
|
@ -839,6 +851,12 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
NSWindowCollectionBehaviorManaged;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
else
|
||||
{
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenNone;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
|
||||
if (wndconfig->floating)
|
||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||
|
@ -895,10 +913,10 @@ float _glfwTransformYCocoa(float y)
|
|||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwCreateWindowCocoa(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
|
@ -933,13 +951,31 @@ int _glfwCreateWindowCocoa(_GLFWwindow* window,
|
|||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwRefreshContextAttribs(window, ctxconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (wndconfig->mousePassthrough)
|
||||
_glfwSetWindowMousePassthroughCocoa(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
_glfwShowWindowCocoa(window);
|
||||
_glfwFocusWindowCocoa(window);
|
||||
acquireMonitor(window);
|
||||
|
||||
if (wndconfig->centerCursor)
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
_glfwShowWindowCocoa(window);
|
||||
if (wndconfig->focused)
|
||||
_glfwFocusWindowCocoa(window);
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
@ -1219,9 +1255,10 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
|
|||
{
|
||||
const NSRect contentRect =
|
||||
NSMakeRect(xpos, _glfwTransformYCocoa(ypos + height - 1), width, height);
|
||||
const NSUInteger styleMask = [window->ns.object styleMask];
|
||||
const NSRect frameRect =
|
||||
[window->ns.object frameRectForContentRect:contentRect
|
||||
styleMask:getStyleMask(window)];
|
||||
styleMask:styleMask];
|
||||
|
||||
[window->ns.object setFrame:frameRect display:YES];
|
||||
}
|
||||
|
@ -1238,7 +1275,27 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
|
|||
// TODO: Solve this in a less terrible way
|
||||
_glfwPollEventsCocoa();
|
||||
|
||||
const NSUInteger styleMask = getStyleMask(window);
|
||||
NSUInteger styleMask = [window->ns.object styleMask];
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (window->decorated)
|
||||
{
|
||||
styleMask &= ~NSWindowStyleMaskBorderless;
|
||||
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
|
||||
}
|
||||
|
||||
if (window->resizable)
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
else
|
||||
styleMask &= ~NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
[window->ns.object setStyleMask:styleMask];
|
||||
// HACK: Changing the style mask can cause the first responder to be cleared
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
|
@ -1284,6 +1341,20 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
|
|||
else
|
||||
[window->ns.object setLevel:NSNormalWindowLevel];
|
||||
|
||||
if (window->resizable)
|
||||
{
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenPrimary |
|
||||
NSWindowCollectionBehaviorManaged;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
else
|
||||
{
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenNone;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
|
||||
[window->ns.object setHasShadow:YES];
|
||||
// HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
|
||||
// title property but the miniwindow title property is unaffected
|
||||
|
@ -1293,35 +1364,40 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwWindowFocusedCocoa(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return [window->ns.object isKeyWindow];
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwWindowIconifiedCocoa(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return [window->ns.object isMiniaturized];
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwWindowVisibleCocoa(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return [window->ns.object isVisible];
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwWindowMaximizedCocoa(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return [window->ns.object isZoomed];
|
||||
|
||||
if (window->resizable)
|
||||
return [window->ns.object isZoomed];
|
||||
else
|
||||
return GLFW_FALSE;
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwWindowHoveredCocoa(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
|
@ -1339,7 +1415,7 @@ int _glfwWindowHoveredCocoa(_GLFWwindow* window)
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwFramebufferTransparentCocoa(_GLFWwindow* window)
|
||||
GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
|
||||
|
@ -1349,15 +1425,46 @@ int _glfwFramebufferTransparentCocoa(_GLFWwindow* window)
|
|||
void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
@autoreleasepool {
|
||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
||||
|
||||
const NSUInteger styleMask = [window->ns.object styleMask];
|
||||
if (enabled)
|
||||
{
|
||||
[window->ns.object setStyleMask:(styleMask | NSWindowStyleMaskResizable)];
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenPrimary |
|
||||
NSWindowCollectionBehaviorManaged;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
else
|
||||
{
|
||||
[window->ns.object setStyleMask:(styleMask & ~NSWindowStyleMaskResizable)];
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenNone;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
@autoreleasepool {
|
||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
||||
|
||||
NSUInteger styleMask = [window->ns.object styleMask];
|
||||
if (enabled)
|
||||
{
|
||||
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
|
||||
styleMask &= ~NSWindowStyleMaskBorderless;
|
||||
}
|
||||
else
|
||||
{
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
|
||||
}
|
||||
|
||||
[window->ns.object setStyleMask:styleMask];
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
|
@ -1530,8 +1637,16 @@ void _glfwSetCursorPosCocoa(_GLFWwindow* window, double x, double y)
|
|||
void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (mode == GLFW_CURSOR_CAPTURED)
|
||||
{
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Cocoa: Captured cursor mode not yet implemented");
|
||||
}
|
||||
|
||||
if (_glfwWindowFocusedCocoa(window))
|
||||
updateCursorMode(window);
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
|
@ -1589,9 +1704,9 @@ int _glfwGetKeyScancodeCocoa(int key)
|
|||
return _glfw.ns.scancodes[key];
|
||||
}
|
||||
|
||||
int _glfwCreateCursorCocoa(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
|
@ -1633,7 +1748,7 @@ int _glfwCreateCursorCocoa(_GLFWcursor* cursor,
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape)
|
||||
GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
|
@ -1816,9 +1931,9 @@ void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions)
|
|||
}
|
||||
}
|
||||
|
||||
int _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
@ -1934,3 +2049,5 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
|
|||
return window->ns.object;
|
||||
}
|
||||
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
|
|
|
@ -48,16 +48,6 @@
|
|||
//
|
||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
if (ctxconfig->share)
|
||||
{
|
||||
if (ctxconfig->client == GLFW_NO_API ||
|
||||
ctxconfig->share->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
||||
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
|
||||
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
|
||||
|
@ -78,6 +68,23 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->share)
|
||||
{
|
||||
if (ctxconfig->client == GLFW_NO_API ||
|
||||
ctxconfig->share->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->source != ctxconfig->share->context.source)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Context creation APIs do not match between contexts");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
|
||||
|
@ -609,10 +616,12 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
|||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
_GLFWwindow* previous;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
if (window && window->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
||||
|
|
|
@ -88,13 +88,30 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
|||
// Return the EGLConfig most closely matching the specified hints
|
||||
//
|
||||
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* desired,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
EGLConfig* result)
|
||||
{
|
||||
EGLConfig* nativeConfigs;
|
||||
_GLFWfbconfig* usableConfigs;
|
||||
const _GLFWfbconfig* closest;
|
||||
int i, nativeCount, usableCount;
|
||||
int i, nativeCount, usableCount, apiBit;
|
||||
GLFWbool wrongApiAvailable = GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
if (ctxconfig->major == 1)
|
||||
apiBit = EGL_OPENGL_ES_BIT;
|
||||
else
|
||||
apiBit = EGL_OPENGL_ES2_BIT;
|
||||
}
|
||||
else
|
||||
apiBit = EGL_OPENGL_BIT;
|
||||
|
||||
if (fbconfig->stereo)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
||||
if (!nativeCount)
|
||||
|
@ -132,7 +149,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||
if (!vi.visualid)
|
||||
continue;
|
||||
|
||||
if (desired->transparent)
|
||||
if (fbconfig->transparent)
|
||||
{
|
||||
int count;
|
||||
XVisualInfo* vis =
|
||||
|
@ -146,23 +163,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||
}
|
||||
#endif // _GLFW_X11
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit))
|
||||
{
|
||||
if (ctxconfig->major == 1)
|
||||
{
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
|
||||
continue;
|
||||
wrongApiAvailable = GLFW_TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
|
||||
|
@ -173,16 +177,60 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
|
||||
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
||||
|
||||
#if defined(_GLFW_WAYLAND)
|
||||
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
|
||||
{
|
||||
// NOTE: The wl_surface opaque region is no guarantee that its buffer
|
||||
// is presented as opaque, if it also has an alpha channel
|
||||
// HACK: If EGL_EXT_present_opaque is unavailable, ignore any config
|
||||
// with an alpha channel to ensure the buffer is opaque
|
||||
if (!_glfw.egl.EXT_present_opaque)
|
||||
{
|
||||
if (!fbconfig->transparent && u->alphaBits > 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif // _GLFW_WAYLAND
|
||||
|
||||
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
||||
u->doublebuffer = desired->doublebuffer;
|
||||
u->doublebuffer = fbconfig->doublebuffer;
|
||||
|
||||
u->handle = (uintptr_t) n;
|
||||
usableCount++;
|
||||
}
|
||||
|
||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
||||
if (closest)
|
||||
*result = (EGLConfig) closest->handle;
|
||||
else
|
||||
{
|
||||
if (wrongApiAvailable)
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
if (ctxconfig->major == 1)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to find support for OpenGL ES 1.x");
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to find support for OpenGL ES 2 or later");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to find support for OpenGL");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
}
|
||||
}
|
||||
|
||||
_glfw_free(nativeConfigs);
|
||||
_glfw_free(usableConfigs);
|
||||
|
@ -325,7 +373,7 @@ GLFWbool _glfwInitEGL(void)
|
|||
"libEGL.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libEGL-1.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
"libEGL.so",
|
||||
#else
|
||||
"libEGL.so.1",
|
||||
|
@ -506,7 +554,7 @@ void _glfwTerminateEGL(void)
|
|||
}
|
||||
}
|
||||
|
||||
#define setAttrib(a, v) \
|
||||
#define SET_ATTRIB(a, v) \
|
||||
{ \
|
||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
|
@ -535,11 +583,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
share = ctxconfig->share->context.egl.handle;
|
||||
|
||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
|
@ -584,13 +628,13 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
}
|
||||
|
||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
|
@ -599,42 +643,42 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.egl.KHR_create_context_no_error)
|
||||
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
SET_ATTRIB(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
SET_ATTRIB(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
SET_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
|
||||
if (flags)
|
||||
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
SET_ATTRIB(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
SET_ATTRIB(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
}
|
||||
|
||||
if (_glfw.egl.KHR_context_flush_control)
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||
SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||
SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
SET_ATTRIB(EGL_NONE, EGL_NONE);
|
||||
|
||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||
config, share, attribs);
|
||||
|
@ -653,16 +697,16 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
SET_ATTRIB(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
if (!fbconfig->doublebuffer)
|
||||
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
|
||||
SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
|
||||
|
||||
if (_glfw.egl.EXT_present_opaque)
|
||||
setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
|
||||
SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
SET_ATTRIB(EGL_NONE, EGL_NONE);
|
||||
|
||||
native = _glfw.platform.getEGLNativeWindow(window);
|
||||
// HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT
|
||||
|
@ -702,7 +746,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
"libGLES_CM.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
"libGLESv1_CM.dylib",
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
"libGLESv1_CM.so",
|
||||
#else
|
||||
"libGLESv1_CM.so.1",
|
||||
|
@ -721,7 +765,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
"libGLESv2.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGLESv2-2.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
"libGLESv2.so",
|
||||
#else
|
||||
"libGLESv2.so.2",
|
||||
|
@ -734,9 +778,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
_GLFW_OPENGL_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
"libGL.so",
|
||||
#else
|
||||
"libOpenGL.so.0",
|
||||
"libGL.so.1",
|
||||
#endif
|
||||
NULL
|
||||
|
@ -782,7 +827,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
#undef SET_ATTRIB
|
||||
|
||||
// Returns the Visual and depth of the chosen EGLConfig
|
||||
//
|
||||
|
@ -799,11 +844,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
|||
const long vimask = VisualScreenMask | VisualIDMask;
|
||||
|
||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(_glfw.egl.display, native,
|
||||
EGL_NATIVE_VISUAL_ID, &visualID);
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
@ -226,7 +228,10 @@ static GLFWglproc getProcAddressGLX(const char* procname)
|
|||
else if (_glfw.glx.GetProcAddressARB)
|
||||
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
|
||||
else
|
||||
{
|
||||
// NOTE: glvnd provides GLX 1.4, so this can only happen with libGL
|
||||
return _glfwPlatformGetModuleSymbol(_glfw.glx.handle, procname);
|
||||
}
|
||||
}
|
||||
|
||||
static void destroyContextGLX(_GLFWwindow* window)
|
||||
|
@ -259,9 +264,10 @@ GLFWbool _glfwInitGLX(void)
|
|||
_GLFW_GLX_LIBRARY,
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGL-1.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
"libGL.so",
|
||||
#else
|
||||
"libGLX.so.0",
|
||||
"libGL.so.1",
|
||||
"libGL.so",
|
||||
#endif
|
||||
|
@ -308,10 +314,6 @@ GLFWbool _glfwInitGLX(void)
|
|||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXCreateWindow");
|
||||
_glfw.glx.DestroyWindow = (PFNGLXDESTROYWINDOWPROC)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXDestroyWindow");
|
||||
_glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddress");
|
||||
_glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||
_glfw.glx.GetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||
|
||||
|
@ -327,8 +329,6 @@ GLFWbool _glfwInitGLX(void)
|
|||
!_glfw.glx.CreateNewContext ||
|
||||
!_glfw.glx.CreateWindow ||
|
||||
!_glfw.glx.DestroyWindow ||
|
||||
!_glfw.glx.GetProcAddress ||
|
||||
!_glfw.glx.GetProcAddressARB ||
|
||||
!_glfw.glx.GetVisualFromFBConfig)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
|
@ -336,6 +336,12 @@ GLFWbool _glfwInitGLX(void)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// NOTE: Unlike GLX 1.3 entry points these are not required to be present
|
||||
_glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddress");
|
||||
_glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||
|
||||
if (!glXQueryExtension(_glfw.x11.display,
|
||||
&_glfw.glx.errorBase,
|
||||
&_glfw.glx.eventBase))
|
||||
|
@ -435,7 +441,7 @@ void _glfwTerminateGLX(void)
|
|||
}
|
||||
}
|
||||
|
||||
#define setAttrib(a, v) \
|
||||
#define SET_ATTRIB(a, v) \
|
||||
{ \
|
||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
|
@ -523,13 +529,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
}
|
||||
|
||||
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
|
@ -542,13 +548,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +562,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.glx.ARB_create_context_no_error)
|
||||
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
SET_ATTRIB(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
}
|
||||
|
||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||
|
@ -564,17 +570,17 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||
// highest version supported by the driver
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
SET_ATTRIB(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
SET_ATTRIB(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
SET_ATTRIB(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
if (flags)
|
||||
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
SET_ATTRIB(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
setAttrib(None, None);
|
||||
SET_ATTRIB(None, None);
|
||||
|
||||
window->context.glx.handle =
|
||||
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
|
||||
|
@ -631,7 +637,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
#undef SET_ATTRIB
|
||||
|
||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||
//
|
||||
|
@ -710,3 +716,5 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
|
|||
return window->context.glx.window;
|
||||
}
|
||||
|
||||
#endif // _GLFW_X11
|
||||
|
||||
|
|
|
@ -171,6 +171,59 @@ size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)
|
|||
return count;
|
||||
}
|
||||
|
||||
// Splits and translates a text/uri-list into separate file paths
|
||||
// NOTE: This function destroys the provided string
|
||||
//
|
||||
char** _glfwParseUriList(char* text, int* count)
|
||||
{
|
||||
const char* prefix = "file://";
|
||||
char** paths = NULL;
|
||||
char* line;
|
||||
|
||||
*count = 0;
|
||||
|
||||
while ((line = strtok(text, "\r\n")))
|
||||
{
|
||||
char* path;
|
||||
|
||||
text = NULL;
|
||||
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
if (strncmp(line, prefix, strlen(prefix)) == 0)
|
||||
{
|
||||
line += strlen(prefix);
|
||||
// TODO: Validate hostname
|
||||
while (*line != '/')
|
||||
line++;
|
||||
}
|
||||
|
||||
(*count)++;
|
||||
|
||||
path = _glfw_calloc(strlen(line) + 1, 1);
|
||||
paths = _glfw_realloc(paths, *count * sizeof(char*));
|
||||
paths[*count - 1] = path;
|
||||
|
||||
while (*line)
|
||||
{
|
||||
if (line[0] == '%' && line[1] && line[2])
|
||||
{
|
||||
const char digits[3] = { line[1], line[2], '\0' };
|
||||
*path = (char) strtol(digits, NULL, 16);
|
||||
line += 2;
|
||||
}
|
||||
else
|
||||
*path = *line;
|
||||
|
||||
path++;
|
||||
line++;
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
char* _glfw_strdup(const char* source)
|
||||
{
|
||||
const size_t length = strlen(source);
|
||||
|
@ -179,6 +232,16 @@ char* _glfw_strdup(const char* source)
|
|||
return result;
|
||||
}
|
||||
|
||||
int _glfw_min(int a, int b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
int _glfw_max(int a, int b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
float _glfw_fminf(float a, float b)
|
||||
{
|
||||
if (a != a)
|
||||
|
|
|
@ -44,6 +44,13 @@
|
|||
#define _GLFW_JOYSTICK_BUTTON 2
|
||||
#define _GLFW_JOYSTICK_HATBIT 3
|
||||
|
||||
#define GLFW_MOD_MASK (GLFW_MOD_SHIFT | \
|
||||
GLFW_MOD_CONTROL | \
|
||||
GLFW_MOD_ALT | \
|
||||
GLFW_MOD_SUPER | \
|
||||
GLFW_MOD_CAPS_LOCK | \
|
||||
GLFW_MOD_NUM_LOCK)
|
||||
|
||||
// Initializes the platform joystick API if it has not been already
|
||||
//
|
||||
static GLFWbool initJoysticks(void)
|
||||
|
@ -266,6 +273,12 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||
//
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(key >= 0 || key == GLFW_KEY_UNKNOWN);
|
||||
assert(key <= GLFW_KEY_LAST);
|
||||
assert(action == GLFW_PRESS || action == GLFW_RELEASE);
|
||||
assert(mods == (mods & GLFW_MOD_MASK));
|
||||
|
||||
if (key >= 0 && key <= GLFW_KEY_LAST)
|
||||
{
|
||||
GLFWbool repeated = GLFW_FALSE;
|
||||
|
@ -297,6 +310,10 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
|
|||
//
|
||||
void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(mods == (mods & GLFW_MOD_MASK));
|
||||
assert(plain == GLFW_TRUE || plain == GLFW_FALSE);
|
||||
|
||||
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
||||
return;
|
||||
|
||||
|
@ -317,6 +334,12 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
|
|||
//
|
||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(xoffset > -FLT_MAX);
|
||||
assert(xoffset < FLT_MAX);
|
||||
assert(yoffset > -FLT_MAX);
|
||||
assert(yoffset < FLT_MAX);
|
||||
|
||||
if (window->callbacks.scroll)
|
||||
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
||||
}
|
||||
|
@ -325,6 +348,12 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
|||
//
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(button >= 0);
|
||||
assert(button <= GLFW_MOUSE_BUTTON_LAST);
|
||||
assert(action == GLFW_PRESS || action == GLFW_RELEASE);
|
||||
assert(mods == (mods & GLFW_MOD_MASK));
|
||||
|
||||
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||
return;
|
||||
|
||||
|
@ -345,6 +374,12 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
|||
//
|
||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(xpos > -FLT_MAX);
|
||||
assert(xpos < FLT_MAX);
|
||||
assert(ypos > -FLT_MAX);
|
||||
assert(ypos < FLT_MAX);
|
||||
|
||||
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
|
||||
return;
|
||||
|
||||
|
@ -359,6 +394,9 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
|||
//
|
||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(entered == GLFW_TRUE || entered == GLFW_FALSE);
|
||||
|
||||
if (window->callbacks.cursorEnter)
|
||||
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||
}
|
||||
|
@ -367,6 +405,10 @@ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
|||
//
|
||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(count > 0);
|
||||
assert(paths != NULL);
|
||||
|
||||
if (window->callbacks.drop)
|
||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||
}
|
||||
|
@ -375,16 +417,26 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
|||
//
|
||||
void _glfwInputJoystick(_GLFWjoystick* js, int event)
|
||||
{
|
||||
const int jid = (int) (js - _glfw.joysticks);
|
||||
assert(js != NULL);
|
||||
assert(event == GLFW_CONNECTED || event == GLFW_DISCONNECTED);
|
||||
|
||||
if (event == GLFW_CONNECTED)
|
||||
js->connected = GLFW_TRUE;
|
||||
else if (event == GLFW_DISCONNECTED)
|
||||
js->connected = GLFW_FALSE;
|
||||
|
||||
if (_glfw.callbacks.joystick)
|
||||
_glfw.callbacks.joystick(jid, event);
|
||||
_glfw.callbacks.joystick((int) (js - _glfw.joysticks), event);
|
||||
}
|
||||
|
||||
// Notifies shared code of the new value of a joystick axis
|
||||
//
|
||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
|
||||
{
|
||||
assert(js != NULL);
|
||||
assert(axis >= 0);
|
||||
assert(axis < js->axisCount);
|
||||
|
||||
js->axes[axis] = value;
|
||||
}
|
||||
|
||||
|
@ -392,6 +444,11 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
|
|||
//
|
||||
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
|
||||
{
|
||||
assert(js != NULL);
|
||||
assert(button >= 0);
|
||||
assert(button < js->buttonCount);
|
||||
assert(value == GLFW_PRESS || value == GLFW_RELEASE);
|
||||
|
||||
js->buttons[button] = value;
|
||||
}
|
||||
|
||||
|
@ -399,7 +456,18 @@ void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
|
|||
//
|
||||
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
|
||||
{
|
||||
const int base = js->buttonCount + hat * 4;
|
||||
int base;
|
||||
|
||||
assert(js != NULL);
|
||||
assert(hat >= 0);
|
||||
assert(hat < js->hatCount);
|
||||
|
||||
// Valid hat values only use the least significant nibble and have at most two bits
|
||||
// set, which can be considered adjacent plus an arbitrary rotation within the nibble
|
||||
assert((value & 0xf0) == 0);
|
||||
assert((value & ((value << 2) | (value >> 2))) == 0);
|
||||
|
||||
base = js->buttonCount + hat * 4;
|
||||
|
||||
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
|
@ -442,7 +510,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
if (!_glfw.joysticks[jid].allocated)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -450,7 +518,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->allocated = GLFW_TRUE;
|
||||
js->axes = _glfw_calloc(axisCount, sizeof(float));
|
||||
js->buttons = _glfw_calloc(buttonCount + (size_t) hatCount * 4, 1);
|
||||
js->hats = _glfw_calloc(hatCount, 1);
|
||||
|
@ -528,7 +596,8 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||
{
|
||||
if (value != GLFW_CURSOR_NORMAL &&
|
||||
value != GLFW_CURSOR_HIDDEN &&
|
||||
value != GLFW_CURSOR_DISABLED)
|
||||
value != GLFW_CURSOR_DISABLED &&
|
||||
value != GLFW_CURSOR_CAPTURED)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid cursor mode 0x%08X",
|
||||
|
@ -764,9 +833,16 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
|
|||
_GLFWcursor* cursor;
|
||||
|
||||
assert(image != NULL);
|
||||
assert(image->pixels != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (image->width <= 0 || image->height <= 0)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor = _glfw_calloc(1, sizeof(_GLFWcursor));
|
||||
cursor->next = _glfw.cursorListHead;
|
||||
_glfw.cursorListHead = cursor;
|
||||
|
@ -965,7 +1041,7 @@ GLFWAPI int glfwJoystickPresent(int jid)
|
|||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return GLFW_FALSE;
|
||||
|
||||
return _glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||
|
@ -993,7 +1069,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_AXES))
|
||||
|
@ -1025,7 +1101,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS))
|
||||
|
@ -1061,7 +1137,7 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS))
|
||||
|
@ -1090,7 +1166,7 @@ GLFWAPI const char* glfwGetJoystickName(int jid)
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
|
@ -1118,7 +1194,7 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
|
@ -1137,7 +1213,7 @@ GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
|
|||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->allocated)
|
||||
return;
|
||||
|
||||
js->userPointer = pointer;
|
||||
|
@ -1153,7 +1229,7 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid)
|
|||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->allocated)
|
||||
return NULL;
|
||||
|
||||
return js->userPointer;
|
||||
|
@ -1223,7 +1299,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
|||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
if (js->connected)
|
||||
js->mapping = findValidMapping(js);
|
||||
}
|
||||
|
||||
|
@ -1249,7 +1325,7 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
|
|||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
|
@ -1277,7 +1353,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid)
|
|||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
|
@ -1312,7 +1388,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
|||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
if (!js->connected)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_ALL))
|
||||
|
@ -1421,3 +1497,4 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void)
|
|||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return _glfwPlatformGetTimerFrequency();
|
||||
}
|
||||
|
||||
|
|
|
@ -330,13 +330,6 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
|
|||
|
||||
#include "platform.h"
|
||||
|
||||
// Constructs a version number string from the public header macros
|
||||
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
||||
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
||||
#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \
|
||||
GLFW_VERSION_MINOR, \
|
||||
GLFW_VERSION_REVISION)
|
||||
|
||||
// Checks for whether the library has been initialized
|
||||
#define _GLFW_REQUIRE_INIT() \
|
||||
if (!_glfw.initialized) \
|
||||
|
@ -396,6 +389,8 @@ struct _GLFWinitconfig
|
|||
//
|
||||
struct _GLFWwndconfig
|
||||
{
|
||||
int xpos;
|
||||
int ypos;
|
||||
int width;
|
||||
int height;
|
||||
const char* title;
|
||||
|
@ -421,6 +416,9 @@ struct _GLFWwndconfig
|
|||
struct {
|
||||
GLFWbool keymenu;
|
||||
} win32;
|
||||
struct {
|
||||
char appId[256];
|
||||
} wl;
|
||||
};
|
||||
|
||||
// Context configuration
|
||||
|
@ -634,7 +632,8 @@ struct _GLFWmapping
|
|||
//
|
||||
struct _GLFWjoystick
|
||||
{
|
||||
GLFWbool present;
|
||||
GLFWbool allocated;
|
||||
GLFWbool connected;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
|
@ -680,8 +679,8 @@ struct _GLFWplatform
|
|||
void (*setCursorMode)(_GLFWwindow*,int);
|
||||
void (*setRawMouseMotion)(_GLFWwindow*,GLFWbool);
|
||||
GLFWbool (*rawMouseMotionSupported)(void);
|
||||
int (*createCursor)(_GLFWcursor*,const GLFWimage*,int,int);
|
||||
int (*createStandardCursor)(_GLFWcursor*,int);
|
||||
GLFWbool (*createCursor)(_GLFWcursor*,const GLFWimage*,int,int);
|
||||
GLFWbool (*createStandardCursor)(_GLFWcursor*,int);
|
||||
void (*destroyCursor)(_GLFWcursor*);
|
||||
void (*setCursor)(_GLFWwindow*,_GLFWcursor*);
|
||||
const char* (*getScancodeName)(int);
|
||||
|
@ -690,7 +689,7 @@ struct _GLFWplatform
|
|||
const char* (*getClipboardString)(void);
|
||||
GLFWbool (*initJoysticks)(void);
|
||||
void (*terminateJoysticks)(void);
|
||||
int (*pollJoystick)(_GLFWjoystick*,int);
|
||||
GLFWbool (*pollJoystick)(_GLFWjoystick*,int);
|
||||
const char* (*getMappingName)(void);
|
||||
void (*updateGamepadGUID)(char*);
|
||||
// monitor
|
||||
|
@ -703,7 +702,7 @@ struct _GLFWplatform
|
|||
GLFWbool (*getGammaRamp)(_GLFWmonitor*,GLFWgammaramp*);
|
||||
void (*setGammaRamp)(_GLFWmonitor*,const GLFWgammaramp*);
|
||||
// window
|
||||
int (*createWindow)(_GLFWwindow*,const _GLFWwndconfig*,const _GLFWctxconfig*,const _GLFWfbconfig*);
|
||||
GLFWbool (*createWindow)(_GLFWwindow*,const _GLFWwndconfig*,const _GLFWctxconfig*,const _GLFWfbconfig*);
|
||||
void (*destroyWindow)(_GLFWwindow*);
|
||||
void (*setWindowTitle)(_GLFWwindow*,const char*);
|
||||
void (*setWindowIcon)(_GLFWwindow*,int,const GLFWimage*);
|
||||
|
@ -724,12 +723,12 @@ struct _GLFWplatform
|
|||
void (*requestWindowAttention)(_GLFWwindow*);
|
||||
void (*focusWindow)(_GLFWwindow*);
|
||||
void (*setWindowMonitor)(_GLFWwindow*,_GLFWmonitor*,int,int,int,int,int);
|
||||
int (*windowFocused)(_GLFWwindow*);
|
||||
int (*windowIconified)(_GLFWwindow*);
|
||||
int (*windowVisible)(_GLFWwindow*);
|
||||
int (*windowMaximized)(_GLFWwindow*);
|
||||
int (*windowHovered)(_GLFWwindow*);
|
||||
int (*framebufferTransparent)(_GLFWwindow*);
|
||||
GLFWbool (*windowFocused)(_GLFWwindow*);
|
||||
GLFWbool (*windowIconified)(_GLFWwindow*);
|
||||
GLFWbool (*windowVisible)(_GLFWwindow*);
|
||||
GLFWbool (*windowMaximized)(_GLFWwindow*);
|
||||
GLFWbool (*windowHovered)(_GLFWwindow*);
|
||||
GLFWbool (*framebufferTransparent)(_GLFWwindow*);
|
||||
float (*getWindowOpacity)(_GLFWwindow*);
|
||||
void (*setWindowResizable)(_GLFWwindow*,GLFWbool);
|
||||
void (*setWindowDecorated)(_GLFWwindow*,GLFWbool);
|
||||
|
@ -746,7 +745,7 @@ struct _GLFWplatform
|
|||
EGLNativeWindowType (*getEGLNativeWindow)(_GLFWwindow*);
|
||||
// vulkan
|
||||
void (*getRequiredInstanceExtensions)(char**);
|
||||
int (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t);
|
||||
GLFWbool (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t);
|
||||
VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
};
|
||||
|
||||
|
@ -996,8 +995,11 @@ void _glfwTerminateVulkan(void);
|
|||
const char* _glfwGetVulkanResultString(VkResult result);
|
||||
|
||||
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
|
||||
char** _glfwParseUriList(char* text, int* count);
|
||||
|
||||
char* _glfw_strdup(const char* source);
|
||||
int _glfw_min(int a, int b);
|
||||
int _glfw_max(int a, int b);
|
||||
float _glfw_fminf(float a, float b);
|
||||
float _glfw_fmaxf(float a, float b);
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/inotify.h>
|
||||
|
@ -128,7 +130,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||
{
|
||||
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
if (!_glfw.joysticks[jid].connected)
|
||||
continue;
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
return GLFW_FALSE;
|
||||
|
@ -157,7 +159,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||
}
|
||||
|
||||
// Ensure this device supports the events expected of a joystick
|
||||
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||
if (!isBitSet(EV_ABS, evBits))
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
|
@ -245,9 +247,9 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||
//
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
close(js->linjs.fd);
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Lexically compare joysticks by name; used by qsort
|
||||
|
@ -366,7 +368,7 @@ void _glfwTerminateJoysticksLinux(void)
|
|||
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
if (js->connected)
|
||||
closeJoystick(js);
|
||||
}
|
||||
|
||||
|
@ -380,7 +382,7 @@ void _glfwTerminateJoysticksLinux(void)
|
|||
}
|
||||
}
|
||||
|
||||
int _glfwPollJoystickLinux(_GLFWjoystick* js, int mode)
|
||||
GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
// Read all queued events (non-blocking)
|
||||
for (;;)
|
||||
|
@ -417,7 +419,7 @@ int _glfwPollJoystickLinux(_GLFWjoystick* js, int mode)
|
|||
handleAbsEvent(js, e.code, e.value);
|
||||
}
|
||||
|
||||
return js->present;
|
||||
return js->connected;
|
||||
}
|
||||
|
||||
const char* _glfwGetMappingNameLinux(void)
|
||||
|
@ -429,3 +431,5 @@ void _glfwUpdateGamepadGUIDLinux(char* guid)
|
|||
{
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_LINUX_JOYSTICK
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#define GLFW_LINUX_JOYSTICK_STATE _GLFWjoystickLinux linjs;
|
||||
#define GLFW_LINUX_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs;
|
||||
|
||||
#define GLFW_BUILD_LINUX_MAPPINGS
|
||||
|
||||
// Linux-specific joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickLinux
|
||||
|
@ -59,7 +57,7 @@ void _glfwDetectJoystickConnectionLinux(void);
|
|||
|
||||
GLFWbool _glfwInitJoysticksLinux(void);
|
||||
void _glfwTerminateJoysticksLinux(void);
|
||||
int _glfwPollJoystickLinux(_GLFWjoystick* js, int mode);
|
||||
GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode);
|
||||
const char* _glfwGetMappingNameLinux(void);
|
||||
void _glfwUpdateGamepadGUIDLinux(char* guid);
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
const char* _glfwDefaultMappings[] =
|
||||
{
|
||||
#if defined(GLFW_BUILD_WIN32_MAPPINGS)
|
||||
#if defined(_GLFW_WIN32)
|
||||
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
|
||||
"03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
|
||||
"03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,",
|
||||
|
@ -426,9 +426,9 @@ const char* _glfwDefaultMappings[] =
|
|||
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
#endif // GLFW_BUILD_WIN32_MAPPINGS
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
#if defined(GLFW_BUILD_COCOA_MAPPINGS)
|
||||
#if defined(_GLFW_COCOA)
|
||||
"030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||
"03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||
|
@ -598,9 +598,9 @@ const char* _glfwDefaultMappings[] =
|
|||
"03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||
"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
#endif // GLFW_BUILD_COCOA_MAPPINGS
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
#if defined(GLFW_BUILD_LINUX_MAPPINGS)
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,",
|
||||
|
@ -996,6 +996,6 @@ const char* _glfwDefaultMappings[] =
|
|||
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
|
||||
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
#endif // GLFW_BUILD_LINUX_MAPPINGS
|
||||
#endif // GLFW_BUILD_LINUX_JOYSTICK
|
||||
};
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
const char* _glfwDefaultMappings[] =
|
||||
{
|
||||
#if defined(GLFW_BUILD_WIN32_MAPPINGS)
|
||||
#if defined(_GLFW_WIN32)
|
||||
@GLFW_WIN32_MAPPINGS@
|
||||
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
|
@ -69,14 +69,14 @@ const char* _glfwDefaultMappings[] =
|
|||
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
#endif // GLFW_BUILD_WIN32_MAPPINGS
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
#if defined(GLFW_BUILD_COCOA_MAPPINGS)
|
||||
#if defined(_GLFW_COCOA)
|
||||
@GLFW_COCOA_MAPPINGS@
|
||||
#endif // GLFW_BUILD_COCOA_MAPPINGS
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
#if defined(GLFW_BUILD_LINUX_MAPPINGS)
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
@GLFW_LINUX_MAPPINGS@
|
||||
#endif // GLFW_BUILD_LINUX_MAPPINGS
|
||||
#endif // GLFW_BUILD_LINUX_JOYSTICK
|
||||
};
|
||||
|
||||
|
|
|
@ -96,6 +96,10 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
|||
//
|
||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
||||
{
|
||||
assert(monitor != NULL);
|
||||
assert(action == GLFW_CONNECTED || action == GLFW_DISCONNECTED);
|
||||
assert(placement == _GLFW_INSERT_FIRST || placement == _GLFW_INSERT_LAST);
|
||||
|
||||
if (action == GLFW_CONNECTED)
|
||||
{
|
||||
_glfw.monitorCount++;
|
||||
|
@ -155,6 +159,7 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
|||
//
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
{
|
||||
assert(monitor != NULL);
|
||||
monitor->window = window;
|
||||
}
|
||||
|
||||
|
@ -522,6 +527,8 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
|||
assert(ramp->green != NULL);
|
||||
assert(ramp->blue != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (ramp->size <= 0)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
|
@ -530,8 +537,6 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
|||
return;
|
||||
}
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (!monitor->originalRamp.size)
|
||||
{
|
||||
if (!_glfw.platform.getGammaRamp(monitor, &monitor->originalRamp))
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -188,45 +190,45 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
|
||||
// are not a hard constraint, so ignore and continue
|
||||
|
||||
#define addAttrib(a) \
|
||||
#define ADD_ATTRIB(a) \
|
||||
{ \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
}
|
||||
#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
|
||||
#define SET_ATTRIB(a, v) { ADD_ATTRIB(a); ADD_ATTRIB(v); }
|
||||
|
||||
NSOpenGLPixelFormatAttribute attribs[40];
|
||||
int index = 0;
|
||||
|
||||
addAttrib(NSOpenGLPFAAccelerated);
|
||||
addAttrib(NSOpenGLPFAClosestPolicy);
|
||||
ADD_ATTRIB(NSOpenGLPFAAccelerated);
|
||||
ADD_ATTRIB(NSOpenGLPFAClosestPolicy);
|
||||
|
||||
if (ctxconfig->nsgl.offline)
|
||||
{
|
||||
addAttrib(NSOpenGLPFAAllowOfflineRenderers);
|
||||
ADD_ATTRIB(NSOpenGLPFAAllowOfflineRenderers);
|
||||
// NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
|
||||
// Info.plist for unbundled applications
|
||||
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
||||
// a straightforward wrapper of its CGL counterpart
|
||||
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||
ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||
if (ctxconfig->major >= 4)
|
||||
{
|
||||
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
}
|
||||
else
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
if (ctxconfig->major >= 3)
|
||||
{
|
||||
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
}
|
||||
|
||||
if (ctxconfig->major <= 2)
|
||||
{
|
||||
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
||||
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||
SET_ATTRIB(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||
|
||||
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
|
||||
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
|
||||
|
@ -238,7 +240,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||
fbconfig->accumBlueBits +
|
||||
fbconfig->accumAlphaBits;
|
||||
|
||||
setAttrib(NSOpenGLPFAAccumSize, accumBits);
|
||||
SET_ATTRIB(NSOpenGLPFAAccumSize, accumBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,17 +258,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||
else if (colorBits < 15)
|
||||
colorBits = 15;
|
||||
|
||||
setAttrib(NSOpenGLPFAColorSize, colorBits);
|
||||
SET_ATTRIB(NSOpenGLPFAColorSize, colorBits);
|
||||
}
|
||||
|
||||
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
||||
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
SET_ATTRIB(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
|
||||
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
||||
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
SET_ATTRIB(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
|
||||
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
||||
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
SET_ATTRIB(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
|
||||
if (fbconfig->stereo)
|
||||
{
|
||||
|
@ -275,33 +277,33 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||
"NSGL: Stereo rendering is deprecated");
|
||||
return GLFW_FALSE;
|
||||
#else
|
||||
addAttrib(NSOpenGLPFAStereo);
|
||||
ADD_ATTRIB(NSOpenGLPFAStereo);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fbconfig->doublebuffer)
|
||||
addAttrib(NSOpenGLPFADoubleBuffer);
|
||||
ADD_ATTRIB(NSOpenGLPFADoubleBuffer);
|
||||
|
||||
if (fbconfig->samples != GLFW_DONT_CARE)
|
||||
{
|
||||
if (fbconfig->samples == 0)
|
||||
{
|
||||
setAttrib(NSOpenGLPFASampleBuffers, 0);
|
||||
SET_ATTRIB(NSOpenGLPFASampleBuffers, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAttrib(NSOpenGLPFASampleBuffers, 1);
|
||||
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
|
||||
SET_ATTRIB(NSOpenGLPFASampleBuffers, 1);
|
||||
SET_ATTRIB(NSOpenGLPFASamples, fbconfig->samples);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
||||
// framebuffer, so there's no need (and no way) to request it
|
||||
|
||||
addAttrib(0);
|
||||
ADD_ATTRIB(0);
|
||||
|
||||
#undef addAttrib
|
||||
#undef setAttrib
|
||||
#undef ADD_ATTRIB
|
||||
#undef SET_ATTRIB
|
||||
|
||||
window->context.nsgl.pixelFormat =
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||
|
@ -374,3 +376,5 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
|
|||
return window->context.nsgl.object;
|
||||
}
|
||||
|
||||
#endif // _GLFW_COCOA
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void _glfwTerminateJoysticksNull(void)
|
|||
{
|
||||
}
|
||||
|
||||
int _glfwPollJoystickNull(_GLFWjoystick* js, int mode)
|
||||
GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
GLFWbool _glfwInitJoysticksNull(void);
|
||||
void _glfwTerminateJoysticksNull(void);
|
||||
int _glfwPollJoystickNull(_GLFWjoystick* js, int mode);
|
||||
GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode);
|
||||
const char* _glfwGetMappingNameNull(void);
|
||||
void _glfwUpdateGamepadGUIDNull(char* guid);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ void _glfwGetVideoModeNull(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
|||
GLFWbool _glfwGetGammaRampNull(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
void _glfwSetGammaRampNull(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
int _glfwCreateWindowNull(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
GLFWbool _glfwCreateWindowNull(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyWindowNull(_GLFWwindow* window);
|
||||
void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title);
|
||||
void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images);
|
||||
|
@ -102,9 +102,9 @@ void _glfwGetWindowContentScaleNull(_GLFWwindow* window, float* xscale, float* y
|
|||
void _glfwIconifyWindowNull(_GLFWwindow* window);
|
||||
void _glfwRestoreWindowNull(_GLFWwindow* window);
|
||||
void _glfwMaximizeWindowNull(_GLFWwindow* window);
|
||||
int _glfwWindowMaximizedNull(_GLFWwindow* window);
|
||||
int _glfwWindowHoveredNull(_GLFWwindow* window);
|
||||
int _glfwFramebufferTransparentNull(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window);
|
||||
GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window);
|
||||
void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
@ -118,9 +118,9 @@ void _glfwRequestWindowAttentionNull(_GLFWwindow* window);
|
|||
void _glfwRequestWindowAttentionNull(_GLFWwindow* window);
|
||||
void _glfwHideWindowNull(_GLFWwindow* window);
|
||||
void _glfwFocusWindowNull(_GLFWwindow* window);
|
||||
int _glfwWindowFocusedNull(_GLFWwindow* window);
|
||||
int _glfwWindowIconifiedNull(_GLFWwindow* window);
|
||||
int _glfwWindowVisibleNull(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window);
|
||||
void _glfwPollEventsNull(void);
|
||||
void _glfwWaitEventsNull(void);
|
||||
void _glfwWaitEventsTimeoutNull(double timeout);
|
||||
|
@ -128,8 +128,8 @@ void _glfwPostEmptyEventNull(void);
|
|||
void _glfwGetCursorPosNull(_GLFWwindow* window, double* xpos, double* ypos);
|
||||
void _glfwSetCursorPosNull(_GLFWwindow* window, double x, double y);
|
||||
void _glfwSetCursorModeNull(_GLFWwindow* window, int mode);
|
||||
int _glfwCreateCursorNull(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
int _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape);
|
||||
GLFWbool _glfwCreateCursorNull(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape);
|
||||
void _glfwDestroyCursorNull(_GLFWcursor* cursor);
|
||||
void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
void _glfwSetClipboardStringNull(const char* string);
|
||||
|
@ -142,7 +142,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void);
|
|||
EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window);
|
||||
|
||||
void _glfwGetRequiredInstanceExtensionsNull(char** extensions);
|
||||
int _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
void _glfwPollMonitorsNull(void);
|
||||
|
|
|
@ -39,15 +39,15 @@ static void applySizeLimits(_GLFWwindow* window, int* width, int* height)
|
|||
*height = (int) (*width / ratio);
|
||||
}
|
||||
|
||||
if (window->minwidth != GLFW_DONT_CARE && *width < window->minwidth)
|
||||
*width = window->minwidth;
|
||||
else if (window->maxwidth != GLFW_DONT_CARE && *width > window->maxwidth)
|
||||
*width = window->maxwidth;
|
||||
if (window->minwidth != GLFW_DONT_CARE)
|
||||
*width = _glfw_max(*width, window->minwidth);
|
||||
else if (window->maxwidth != GLFW_DONT_CARE)
|
||||
*width = _glfw_min(*width, window->maxwidth);
|
||||
|
||||
if (window->minheight != GLFW_DONT_CARE && *height < window->minheight)
|
||||
*height = window->minheight;
|
||||
else if (window->maxheight != GLFW_DONT_CARE && *height > window->maxheight)
|
||||
*height = window->maxheight;
|
||||
if (window->minheight != GLFW_DONT_CARE)
|
||||
*height = _glfw_min(*height, window->minheight);
|
||||
else if (window->maxheight != GLFW_DONT_CARE)
|
||||
*height = _glfw_max(*height, window->maxheight);
|
||||
}
|
||||
|
||||
static void fitToMonitor(_GLFWwindow* window)
|
||||
|
@ -82,8 +82,17 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
fitToMonitor(window);
|
||||
else
|
||||
{
|
||||
window->null.xpos = 17;
|
||||
window->null.ypos = 17;
|
||||
if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION)
|
||||
{
|
||||
window->null.xpos = 17;
|
||||
window->null.ypos = 17;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->null.xpos = wndconfig->xpos;
|
||||
window->null.ypos = wndconfig->ypos;
|
||||
}
|
||||
|
||||
window->null.width = wndconfig->width;
|
||||
window->null.height = wndconfig->height;
|
||||
}
|
||||
|
@ -103,10 +112,10 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwCreateWindowNull(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
@ -128,13 +137,31 @@ int _glfwCreateWindowNull(_GLFWwindow* window,
|
|||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwRefreshContextAttribs(window, ctxconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (wndconfig->mousePassthrough)
|
||||
_glfwSetWindowMousePassthroughNull(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
_glfwShowWindowNull(window);
|
||||
_glfwFocusWindowNull(window);
|
||||
acquireMonitor(window);
|
||||
|
||||
if (wndconfig->centerCursor)
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
_glfwShowWindowNull(window);
|
||||
if (wndconfig->focused)
|
||||
_glfwFocusWindowNull(window);
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
@ -344,12 +371,12 @@ void _glfwMaximizeWindowNull(_GLFWwindow* window)
|
|||
}
|
||||
}
|
||||
|
||||
int _glfwWindowMaximizedNull(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window)
|
||||
{
|
||||
return window->null.maximized;
|
||||
}
|
||||
|
||||
int _glfwWindowHoveredNull(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window)
|
||||
{
|
||||
return _glfw.null.xcursor >= window->null.xpos &&
|
||||
_glfw.null.ycursor >= window->null.ypos &&
|
||||
|
@ -357,7 +384,7 @@ int _glfwWindowHoveredNull(_GLFWwindow* window)
|
|||
_glfw.null.ycursor <= window->null.ypos + window->null.height - 1;
|
||||
}
|
||||
|
||||
int _glfwFramebufferTransparentNull(_GLFWwindow* window)
|
||||
GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window)
|
||||
{
|
||||
return window->null.transparent;
|
||||
}
|
||||
|
@ -443,17 +470,17 @@ void _glfwFocusWindowNull(_GLFWwindow* window)
|
|||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
int _glfwWindowFocusedNull(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window)
|
||||
{
|
||||
return _glfw.null.focusedWindow == window;
|
||||
}
|
||||
|
||||
int _glfwWindowIconifiedNull(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window)
|
||||
{
|
||||
return window->null.iconified;
|
||||
}
|
||||
|
||||
int _glfwWindowVisibleNull(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window)
|
||||
{
|
||||
return window->null.visible;
|
||||
}
|
||||
|
@ -492,14 +519,14 @@ void _glfwSetCursorModeNull(_GLFWwindow* window, int mode)
|
|||
{
|
||||
}
|
||||
|
||||
int _glfwCreateCursorNull(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
GLFWbool _glfwCreateCursorNull(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
int _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape)
|
||||
GLFWbool _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
@ -675,9 +702,9 @@ void _glfwGetRequiredInstanceExtensionsNull(char** extensions)
|
|||
{
|
||||
}
|
||||
|
||||
int _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ GLFWbool _glfwInitOSMesa(void)
|
|||
"libOSMesa.8.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libOSMesa-8.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
"libOSMesa.so",
|
||||
#else
|
||||
"libOSMesa.so.8",
|
||||
|
@ -190,7 +190,7 @@ void _glfwTerminateOSMesa(void)
|
|||
}
|
||||
}
|
||||
|
||||
#define setAttrib(a, v) \
|
||||
#define SET_ATTRIB(a, v) \
|
||||
{ \
|
||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
|
@ -221,24 +221,24 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||
{
|
||||
int index = 0, attribs[40];
|
||||
|
||||
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
|
||||
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
|
||||
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
|
||||
setAttrib(OSMESA_ACCUM_BITS, accumBits);
|
||||
SET_ATTRIB(OSMESA_FORMAT, OSMESA_RGBA);
|
||||
SET_ATTRIB(OSMESA_DEPTH_BITS, fbconfig->depthBits);
|
||||
SET_ATTRIB(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
|
||||
SET_ATTRIB(OSMESA_ACCUM_BITS, accumBits);
|
||||
|
||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||
{
|
||||
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
|
||||
SET_ATTRIB(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
|
||||
}
|
||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||
{
|
||||
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
|
||||
SET_ATTRIB(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
|
||||
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
|
||||
SET_ATTRIB(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
|
||||
SET_ATTRIB(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (ctxconfig->forward)
|
||||
|
@ -248,7 +248,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
setAttrib(0, 0);
|
||||
SET_ATTRIB(0, 0);
|
||||
|
||||
window->context.osmesa.handle =
|
||||
OSMesaCreateContextAttribs(attribs, share);
|
||||
|
@ -287,7 +287,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
#undef SET_ATTRIB
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
// These construct a string literal from individual numeric constants
|
||||
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
||||
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -146,7 +150,9 @@ GLFWAPI int glfwPlatformSupported(int platformID)
|
|||
|
||||
GLFWAPI const char* glfwGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER
|
||||
return _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR,
|
||||
GLFW_VERSION_MINOR,
|
||||
GLFW_VERSION_REVISION)
|
||||
#if defined(_GLFW_WIN32)
|
||||
" Win32 WGL"
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,18 @@
|
|||
//
|
||||
//========================================================================
|
||||
|
||||
#if defined(GLFW_BUILD_WIN32_TIMER) || \
|
||||
defined(GLFW_BUILD_WIN32_MODULE) || \
|
||||
defined(GLFW_BUILD_WIN32_THREAD) || \
|
||||
defined(GLFW_BUILD_COCOA_TIMER) || \
|
||||
defined(GLFW_BUILD_POSIX_TIMER) || \
|
||||
defined(GLFW_BUILD_POSIX_MODULE) || \
|
||||
defined(GLFW_BUILD_POSIX_THREAD) || \
|
||||
defined(GLFW_BUILD_POSIX_POLL) || \
|
||||
defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
#error "You must not define these; define zero or more _GLFW_<platform> macros instead"
|
||||
#endif
|
||||
|
||||
#include "null_platform.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
|
@ -86,36 +98,16 @@
|
|||
#endif
|
||||
|
||||
#if (defined(_GLFW_X11) || defined(_GLFW_WAYLAND)) && defined(__linux__)
|
||||
#define GLFW_BUILD_LINUX_JOYSTICK
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
#include "linux_joystick.h"
|
||||
#else
|
||||
#define GLFW_LINUX_JOYSTICK_STATE
|
||||
#define GLFW_LINUX_LIBRARY_JOYSTICK_STATE
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "win32_thread.h"
|
||||
#define GLFW_POSIX_TLS_STATE
|
||||
#define GLFW_POSIX_MUTEX_STATE
|
||||
#else
|
||||
#include "posix_thread.h"
|
||||
#define GLFW_WIN32_TLS_STATE
|
||||
#define GLFW_WIN32_MUTEX_STATE
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "win32_time.h"
|
||||
#define GLFW_POSIX_LIBRARY_TIMER_STATE
|
||||
#define GLFW_COCOA_LIBRARY_TIMER_STATE
|
||||
#elif defined(__APPLE__)
|
||||
#include "cocoa_time.h"
|
||||
#define GLFW_WIN32_LIBRARY_TIMER_STATE
|
||||
#define GLFW_POSIX_LIBRARY_TIMER_STATE
|
||||
#else
|
||||
#include "posix_time.h"
|
||||
#define GLFW_WIN32_LIBRARY_TIMER_STATE
|
||||
#define GLFW_COCOA_LIBRARY_TIMER_STATE
|
||||
#endif
|
||||
|
||||
#define GLFW_PLATFORM_WINDOW_STATE \
|
||||
GLFW_WIN32_WINDOW_STATE \
|
||||
GLFW_COCOA_WINDOW_STATE \
|
||||
|
@ -142,14 +134,6 @@
|
|||
GLFW_COCOA_JOYSTICK_STATE \
|
||||
GLFW_LINUX_JOYSTICK_STATE
|
||||
|
||||
#define GLFW_PLATFORM_TLS_STATE \
|
||||
GLFW_WIN32_TLS_STATE \
|
||||
GLFW_POSIX_TLS_STATE \
|
||||
|
||||
#define GLFW_PLATFORM_MUTEX_STATE \
|
||||
GLFW_WIN32_MUTEX_STATE \
|
||||
GLFW_POSIX_MUTEX_STATE \
|
||||
|
||||
#define GLFW_PLATFORM_LIBRARY_WINDOW_STATE \
|
||||
GLFW_WIN32_LIBRARY_WINDOW_STATE \
|
||||
GLFW_COCOA_LIBRARY_WINDOW_STATE \
|
||||
|
@ -162,11 +146,6 @@
|
|||
GLFW_COCOA_LIBRARY_JOYSTICK_STATE \
|
||||
GLFW_LINUX_LIBRARY_JOYSTICK_STATE
|
||||
|
||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE \
|
||||
GLFW_WIN32_LIBRARY_TIMER_STATE \
|
||||
GLFW_COCOA_LIBRARY_TIMER_STATE \
|
||||
GLFW_POSIX_LIBRARY_TIMER_STATE \
|
||||
|
||||
#define GLFW_PLATFORM_CONTEXT_STATE \
|
||||
GLFW_WGL_CONTEXT_STATE \
|
||||
GLFW_NSGL_CONTEXT_STATE \
|
||||
|
@ -177,3 +156,48 @@
|
|||
GLFW_NSGL_LIBRARY_CONTEXT_STATE \
|
||||
GLFW_GLX_LIBRARY_CONTEXT_STATE
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define GLFW_BUILD_WIN32_THREAD
|
||||
#else
|
||||
#define GLFW_BUILD_POSIX_THREAD
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_BUILD_WIN32_THREAD)
|
||||
#include "win32_thread.h"
|
||||
#define GLFW_PLATFORM_TLS_STATE GLFW_WIN32_TLS_STATE
|
||||
#define GLFW_PLATFORM_MUTEX_STATE GLFW_WIN32_MUTEX_STATE
|
||||
#elif defined(GLFW_BUILD_POSIX_THREAD)
|
||||
#include "posix_thread.h"
|
||||
#define GLFW_PLATFORM_TLS_STATE GLFW_POSIX_TLS_STATE
|
||||
#define GLFW_PLATFORM_MUTEX_STATE GLFW_POSIX_MUTEX_STATE
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define GLFW_BUILD_WIN32_TIMER
|
||||
#elif defined(__APPLE__)
|
||||
#define GLFW_BUILD_COCOA_TIMER
|
||||
#else
|
||||
#define GLFW_BUILD_POSIX_TIMER
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_BUILD_WIN32_TIMER)
|
||||
#include "win32_time.h"
|
||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
|
||||
#elif defined(GLFW_BUILD_COCOA_TIMER)
|
||||
#include "cocoa_time.h"
|
||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
|
||||
#elif defined(GLFW_BUILD_POSIX_TIMER)
|
||||
#include "posix_time.h"
|
||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define GLFW_BUILD_WIN32_MODULE
|
||||
#else
|
||||
#define GLFW_BUILD_POSIX_MODULE
|
||||
#endif
|
||||
|
||||
#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11)
|
||||
#define GLFW_BUILD_POSIX_POLL
|
||||
#endif
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_POSIX_MODULE)
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -49,3 +51,5 @@ GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
|
|||
return dlsym(module, name);
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_POSIX_MODULE
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
//========================================================================
|
||||
// GLFW 3.4 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
// It is fine to use C99 in this file because it will not be built with VS
|
||||
//========================================================================
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_POSIX_POLL)
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (timeout)
|
||||
{
|
||||
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
|
||||
const time_t seconds = (time_t) *timeout;
|
||||
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||
const struct timespec ts = { seconds, nanoseconds };
|
||||
const int result = ppoll(fds, count, &ts, NULL);
|
||||
#elif defined(__NetBSD__)
|
||||
const time_t seconds = (time_t) *timeout;
|
||||
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||
const struct timespec ts = { seconds, nanoseconds };
|
||||
const int result = pollts(fds, count, &ts, NULL);
|
||||
#else
|
||||
const int milliseconds = (int) (*timeout * 1e3);
|
||||
const int result = poll(fds, count, milliseconds);
|
||||
#endif
|
||||
const int error = errno; // clock_gettime may overwrite our error
|
||||
|
||||
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||
(double) _glfwPlatformGetTimerFrequency();
|
||||
|
||||
if (result > 0)
|
||||
return GLFW_TRUE;
|
||||
else if (result == -1 && error != EINTR && error != EAGAIN)
|
||||
return GLFW_FALSE;
|
||||
else if (*timeout <= 0.0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int result = poll(fds, count, -1);
|
||||
if (result > 0)
|
||||
return GLFW_TRUE;
|
||||
else if (result == -1 && errno != EINTR && errno != EAGAIN)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_POSIX_POLL
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//========================================================================
|
||||
// GLFW 3.4 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
// It is fine to use C99 in this file because it will not be built with VS
|
||||
//========================================================================
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout);
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_POSIX_THREAD)
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -103,3 +105,5 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
|||
pthread_mutex_unlock(&mutex->posix.handle);
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_POSIX_THREAD
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_POSIX_TIMER)
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
@ -61,3 +63,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void)
|
|||
return _glfw.timer.posix.frequency;
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_POSIX_TIMER
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
|
||||
if (!_glfw.vk.handle)
|
||||
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
|
||||
#else
|
||||
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1");
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -52,12 +54,12 @@ static int findPixelFormatAttribValueWGL(const int* attribs,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define addAttrib(a) \
|
||||
#define ADD_ATTRIB(a) \
|
||||
{ \
|
||||
assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[attribCount++] = a; \
|
||||
}
|
||||
#define findAttribValue(a) \
|
||||
#define FIND_ATTRIB_VALUE(a) \
|
||||
findPixelFormatAttribValueWGL(attribs, attribCount, values, a)
|
||||
|
||||
// Return a list of available and usable framebuffer configs
|
||||
|
@ -72,62 +74,50 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
|
|||
int attribs[40];
|
||||
int values[sizeof(attribs) / sizeof(attribs[0])];
|
||||
|
||||
nativeCount = DescribePixelFormat(window->context.wgl.dc,
|
||||
1,
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
NULL);
|
||||
|
||||
if (_glfw.wgl.ARB_pixel_format)
|
||||
{
|
||||
const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
|
||||
|
||||
if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
|
||||
1, 0, 1, &attrib, &nativeCount))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve pixel format attribute");
|
||||
return 0;
|
||||
}
|
||||
|
||||
addAttrib(WGL_SUPPORT_OPENGL_ARB);
|
||||
addAttrib(WGL_DRAW_TO_WINDOW_ARB);
|
||||
addAttrib(WGL_PIXEL_TYPE_ARB);
|
||||
addAttrib(WGL_ACCELERATION_ARB);
|
||||
addAttrib(WGL_RED_BITS_ARB);
|
||||
addAttrib(WGL_RED_SHIFT_ARB);
|
||||
addAttrib(WGL_GREEN_BITS_ARB);
|
||||
addAttrib(WGL_GREEN_SHIFT_ARB);
|
||||
addAttrib(WGL_BLUE_BITS_ARB);
|
||||
addAttrib(WGL_BLUE_SHIFT_ARB);
|
||||
addAttrib(WGL_ALPHA_BITS_ARB);
|
||||
addAttrib(WGL_ALPHA_SHIFT_ARB);
|
||||
addAttrib(WGL_DEPTH_BITS_ARB);
|
||||
addAttrib(WGL_STENCIL_BITS_ARB);
|
||||
addAttrib(WGL_ACCUM_BITS_ARB);
|
||||
addAttrib(WGL_ACCUM_RED_BITS_ARB);
|
||||
addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
|
||||
addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
|
||||
addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
|
||||
addAttrib(WGL_AUX_BUFFERS_ARB);
|
||||
addAttrib(WGL_STEREO_ARB);
|
||||
addAttrib(WGL_DOUBLE_BUFFER_ARB);
|
||||
ADD_ATTRIB(WGL_SUPPORT_OPENGL_ARB);
|
||||
ADD_ATTRIB(WGL_DRAW_TO_WINDOW_ARB);
|
||||
ADD_ATTRIB(WGL_PIXEL_TYPE_ARB);
|
||||
ADD_ATTRIB(WGL_ACCELERATION_ARB);
|
||||
ADD_ATTRIB(WGL_RED_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_RED_SHIFT_ARB);
|
||||
ADD_ATTRIB(WGL_GREEN_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_GREEN_SHIFT_ARB);
|
||||
ADD_ATTRIB(WGL_BLUE_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_BLUE_SHIFT_ARB);
|
||||
ADD_ATTRIB(WGL_ALPHA_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_ALPHA_SHIFT_ARB);
|
||||
ADD_ATTRIB(WGL_DEPTH_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_STENCIL_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_ACCUM_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_ACCUM_RED_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_ACCUM_GREEN_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_ACCUM_BLUE_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB);
|
||||
ADD_ATTRIB(WGL_AUX_BUFFERS_ARB);
|
||||
ADD_ATTRIB(WGL_STEREO_ARB);
|
||||
ADD_ATTRIB(WGL_DOUBLE_BUFFER_ARB);
|
||||
|
||||
if (_glfw.wgl.ARB_multisample)
|
||||
addAttrib(WGL_SAMPLES_ARB);
|
||||
ADD_ATTRIB(WGL_SAMPLES_ARB);
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
|
||||
addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||
ADD_ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_glfw.wgl.EXT_colorspace)
|
||||
addAttrib(WGL_COLORSPACE_EXT);
|
||||
ADD_ATTRIB(WGL_COLORSPACE_EXT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nativeCount = DescribePixelFormat(window->context.wgl.dc,
|
||||
1,
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
NULL);
|
||||
}
|
||||
|
||||
usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||
|
||||
|
@ -152,48 +142,48 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
|
||||
!findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
|
||||
if (!FIND_ATTRIB_VALUE(WGL_SUPPORT_OPENGL_ARB) ||
|
||||
!FIND_ATTRIB_VALUE(WGL_DRAW_TO_WINDOW_ARB))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
|
||||
if (FIND_ATTRIB_VALUE(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
|
||||
continue;
|
||||
|
||||
if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
|
||||
if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
|
||||
continue;
|
||||
|
||||
if (findAttribValue(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
|
||||
if (FIND_ATTRIB_VALUE(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
|
||||
continue;
|
||||
|
||||
u->redBits = findAttribValue(WGL_RED_BITS_ARB);
|
||||
u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
|
||||
u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
|
||||
u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
|
||||
u->redBits = FIND_ATTRIB_VALUE(WGL_RED_BITS_ARB);
|
||||
u->greenBits = FIND_ATTRIB_VALUE(WGL_GREEN_BITS_ARB);
|
||||
u->blueBits = FIND_ATTRIB_VALUE(WGL_BLUE_BITS_ARB);
|
||||
u->alphaBits = FIND_ATTRIB_VALUE(WGL_ALPHA_BITS_ARB);
|
||||
|
||||
u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
|
||||
u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
|
||||
u->depthBits = FIND_ATTRIB_VALUE(WGL_DEPTH_BITS_ARB);
|
||||
u->stencilBits = FIND_ATTRIB_VALUE(WGL_STENCIL_BITS_ARB);
|
||||
|
||||
u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
|
||||
u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
|
||||
u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
|
||||
u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
|
||||
u->accumRedBits = FIND_ATTRIB_VALUE(WGL_ACCUM_RED_BITS_ARB);
|
||||
u->accumGreenBits = FIND_ATTRIB_VALUE(WGL_ACCUM_GREEN_BITS_ARB);
|
||||
u->accumBlueBits = FIND_ATTRIB_VALUE(WGL_ACCUM_BLUE_BITS_ARB);
|
||||
u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
|
||||
|
||||
u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
|
||||
u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
|
||||
|
||||
if (findAttribValue(WGL_STEREO_ARB))
|
||||
if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
|
||||
u->stereo = GLFW_TRUE;
|
||||
|
||||
if (_glfw.wgl.ARB_multisample)
|
||||
u->samples = findAttribValue(WGL_SAMPLES_ARB);
|
||||
u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||
{
|
||||
if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
u->sRGB = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +191,7 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
|
|||
{
|
||||
if (_glfw.wgl.EXT_colorspace)
|
||||
{
|
||||
if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
|
||||
if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
|
||||
u->sRGB = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -290,8 +280,8 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
|
|||
return pixelFormat;
|
||||
}
|
||||
|
||||
#undef addAttrib
|
||||
#undef findAttribValue
|
||||
#undef ADD_ATTRIB
|
||||
#undef FIND_ATTRIB_VALUE
|
||||
|
||||
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||
{
|
||||
|
@ -523,7 +513,7 @@ void _glfwTerminateWGL(void)
|
|||
_glfwPlatformFreeModule(_glfw.wgl.instance);
|
||||
}
|
||||
|
||||
#define setAttrib(a, v) \
|
||||
#define SET_ATTRIB(a, v) \
|
||||
{ \
|
||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
|
@ -631,13 +621,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||
SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
}
|
||||
|
||||
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
|
@ -650,13 +640,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -664,7 +654,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.wgl.ARB_create_context_no_error)
|
||||
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
}
|
||||
|
||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||
|
@ -672,17 +662,17 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||
// highest version supported by the driver
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (flags)
|
||||
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||
SET_ATTRIB(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
if (mask)
|
||||
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
setAttrib(0, 0);
|
||||
SET_ATTRIB(0, 0);
|
||||
|
||||
window->context.wgl.handle =
|
||||
wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
|
||||
|
@ -765,7 +755,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
#undef SET_ATTRIB
|
||||
|
||||
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
||||
{
|
||||
|
@ -788,3 +778,5 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
|||
return window->context.wgl.handle;
|
||||
}
|
||||
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static const GUID _glfw_GUID_DEVINTERFACE_HID =
|
||||
|
@ -71,6 +73,16 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
|||
//
|
||||
static GLFWbool loadLibraries(void)
|
||||
{
|
||||
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
(const WCHAR*) &_glfw,
|
||||
(HMODULE*) &_glfw.win32.instance))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to retrieve own module handle");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll");
|
||||
if (!_glfw.win32.user32.instance)
|
||||
{
|
||||
|
@ -91,6 +103,8 @@ static GLFWbool loadLibraries(void)
|
|||
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDpiForWindow");
|
||||
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
||||
_glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");
|
||||
|
||||
_glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll");
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
|
@ -251,7 +265,6 @@ static void createKeyTables(void)
|
|||
_glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
|
||||
_glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
|
||||
_glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
|
||||
_glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
|
||||
_glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
|
||||
|
@ -320,20 +333,69 @@ static void createKeyTables(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Window procedure for the hidden helper window
|
||||
//
|
||||
static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_DISPLAYCHANGE:
|
||||
_glfwPollMonitorsWin32();
|
||||
break;
|
||||
|
||||
case WM_DEVICECHANGE:
|
||||
{
|
||||
if (!_glfw.joysticksInitialized)
|
||||
break;
|
||||
|
||||
if (wParam == DBT_DEVICEARRIVAL)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickConnectionWin32();
|
||||
}
|
||||
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickDisconnectionWin32();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
// Creates a dummy window for behind-the-scenes work
|
||||
//
|
||||
static GLFWbool createHelperWindow(void)
|
||||
{
|
||||
MSG msg;
|
||||
WNDCLASSEXW wc = { sizeof(wc) };
|
||||
|
||||
wc.style = CS_OWNDC;
|
||||
wc.lpfnWndProc = (WNDPROC) helperWindowProc;
|
||||
wc.hInstance = _glfw.win32.instance;
|
||||
wc.lpszClassName = L"GLFW3 Helper";
|
||||
|
||||
_glfw.win32.helperWindowClass = RegisterClassExW(&wc);
|
||||
if (!_glfw.win32.helperWindowClass)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WIn32: Failed to register helper window class");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.helperWindowHandle =
|
||||
CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||
_GLFW_WNDCLASSNAME,
|
||||
MAKEINTATOM(_glfw.win32.helperWindowClass),
|
||||
L"GLFW message window",
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||
0, 0, 1, 1,
|
||||
NULL, NULL,
|
||||
GetModuleHandleW(NULL),
|
||||
_glfw.win32.instance,
|
||||
NULL);
|
||||
|
||||
if (!_glfw.win32.helperWindowHandle)
|
||||
|
@ -483,7 +545,7 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||
vk = vks[key - GLFW_KEY_KP_0];
|
||||
}
|
||||
else
|
||||
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
||||
vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);
|
||||
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
|
@ -491,6 +553,8 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||
|
||||
if (length == -1)
|
||||
{
|
||||
// This is a dead key, so we need a second simulated key press
|
||||
// to make it output its own character (usually a diacritic)
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
0);
|
||||
|
@ -506,7 +570,8 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
|
||||
// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the
|
||||
// application having a correct embedded manifest
|
||||
//
|
||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
||||
{
|
||||
|
@ -626,16 +691,13 @@ int _glfwInitWin32(void)
|
|||
createKeyTables();
|
||||
_glfwUpdateKeyNamesWin32();
|
||||
|
||||
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1703OrGreaterWin32())
|
||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
else if (IsWindows8Point1OrGreater())
|
||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
else if (IsWindowsVistaOrGreater())
|
||||
SetProcessDPIAware();
|
||||
|
||||
if (!_glfwRegisterWindowClassWin32())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!createHelperWindow())
|
||||
return GLFW_FALSE;
|
||||
|
||||
|
@ -650,15 +712,20 @@ void _glfwTerminateWin32(void)
|
|||
|
||||
if (_glfw.win32.helperWindowHandle)
|
||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||
|
||||
_glfwUnregisterWindowClassWin32();
|
||||
if (_glfw.win32.helperWindowClass)
|
||||
UnregisterClassW(MAKEINTATOM(_glfw.win32.helperWindowClass), _glfw.win32.instance);
|
||||
if (_glfw.win32.mainWindowClass)
|
||||
UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance);
|
||||
|
||||
_glfw_free(_glfw.win32.clipboardString);
|
||||
_glfw_free(_glfw.win32.rawInput);
|
||||
|
||||
_glfwTerminateWGL();
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateOSMesa();
|
||||
|
||||
freeLibraries();
|
||||
}
|
||||
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -256,6 +258,8 @@ static GLFWbool supportsXInput(const GUID* guid)
|
|||
//
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
|
||||
if (js->win32.device)
|
||||
{
|
||||
IDirectInputDevice8_Unacquire(js->win32.device);
|
||||
|
@ -263,9 +267,7 @@ static void closeJoystick(_GLFWjoystick* js)
|
|||
}
|
||||
|
||||
_glfw_free(js->win32.objects);
|
||||
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// DirectInput device object enumeration callback
|
||||
|
@ -357,7 +359,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
if (js->connected)
|
||||
{
|
||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
|
@ -508,7 +510,7 @@ void _glfwDetectJoystickConnectionWin32(void)
|
|||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.joysticks[jid].present &&
|
||||
if (_glfw.joysticks[jid].connected &&
|
||||
_glfw.joysticks[jid].win32.device == NULL &&
|
||||
_glfw.joysticks[jid].win32.index == index)
|
||||
{
|
||||
|
@ -560,7 +562,7 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
if (js->connected)
|
||||
_glfwPollJoystickWin32(js, _GLFW_POLL_PRESENCE);
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +576,7 @@ GLFWbool _glfwInitJoysticksWin32(void)
|
|||
{
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||
if (FAILED(DirectInput8Create(_glfw.win32.instance,
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
|
@ -601,13 +603,13 @@ void _glfwTerminateJoysticksWin32(void)
|
|||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||
}
|
||||
|
||||
int _glfwPollJoystickWin32(_GLFWjoystick* js, int mode)
|
||||
GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
if (js->win32.device)
|
||||
{
|
||||
int i, ai = 0, bi = 0, pi = 0;
|
||||
HRESULT result;
|
||||
DIJOYSTATE state;
|
||||
DIJOYSTATE state = {0};
|
||||
|
||||
IDirectInputDevice8_Poll(js->win32.device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||
|
@ -756,3 +758,5 @@ void _glfwUpdateGamepadGUIDWin32(char* guid)
|
|||
}
|
||||
}
|
||||
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#define GLFW_WIN32_JOYSTICK_STATE _GLFWjoystickWin32 win32;
|
||||
#define GLFW_WIN32_LIBRARY_JOYSTICK_STATE
|
||||
|
||||
#define GLFW_BUILD_WIN32_MAPPINGS
|
||||
|
||||
// Joystick element (axis, button or slider)
|
||||
//
|
||||
typedef struct _GLFWjoyobjectWin32
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_WIN32_MODULE)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -47,3 +49,5 @@ GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
|
|||
return (GLFWproc) GetProcAddress((HMODULE) module, name);
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_WIN32_MODULE
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
@ -381,7 +383,7 @@ void _glfwGetMonitorWorkareaWin32(_GLFWmonitor* monitor,
|
|||
int* width, int* height)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
GetMonitorInfo(monitor->win32.handle, &mi);
|
||||
GetMonitorInfoW(monitor->win32.handle, &mi);
|
||||
|
||||
if (xpos)
|
||||
*xpos = mi.rcWork.left;
|
||||
|
@ -545,3 +547,5 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
|
|||
return monitor->win32.publicDisplayName;
|
||||
}
|
||||
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
|
|
|
@ -162,7 +162,9 @@ typedef enum
|
|||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
||||
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
||||
|
||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
||||
// Replacement for versionhelpers.h macros, as we cannot rely on the
|
||||
// application having a correct embedded manifest
|
||||
//
|
||||
#define IsWindowsVistaOrGreater() \
|
||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
|
||||
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
||||
|
@ -176,9 +178,11 @@ typedef enum
|
|||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
|
||||
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
|
||||
|
||||
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
|
||||
// Windows 10 Anniversary Update
|
||||
#define _glfwIsWindows10Version1607OrGreaterWin32() \
|
||||
_glfwIsWindows10BuildOrGreaterWin32(14393)
|
||||
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
|
||||
// Windows 10 Creators Update
|
||||
#define _glfwIsWindows10Version1703OrGreaterWin32() \
|
||||
_glfwIsWindows10BuildOrGreaterWin32(15063)
|
||||
|
||||
// HACK: Define macros that some xinput.h variants don't
|
||||
|
@ -283,12 +287,14 @@ typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
|
|||
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
||||
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
||||
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
||||
typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT);
|
||||
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
||||
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
||||
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
||||
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
||||
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
||||
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
||||
#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_
|
||||
|
||||
// dwmapi.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||
|
@ -352,10 +358,6 @@ typedef struct VkWin32SurfaceCreateInfoKHR
|
|||
typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
|
||||
|
||||
#if !defined(_GLFW_WNDCLASSNAME)
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
#endif
|
||||
|
||||
#define GLFW_WIN32_WINDOW_STATE _GLFWwindowWin32 win32;
|
||||
#define GLFW_WIN32_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32;
|
||||
#define GLFW_WIN32_MONITOR_STATE _GLFWmonitorWin32 win32;
|
||||
|
@ -436,7 +438,10 @@ typedef struct _GLFWwindowWin32
|
|||
//
|
||||
typedef struct _GLFWlibraryWin32
|
||||
{
|
||||
HINSTANCE instance;
|
||||
HWND helperWindowHandle;
|
||||
ATOM helperWindowClass;
|
||||
ATOM mainWindowClass;
|
||||
HDEVNOTIFY deviceNotificationHandle;
|
||||
int acquiredMonitorCount;
|
||||
char* clipboardString;
|
||||
|
@ -447,6 +452,8 @@ typedef struct _GLFWlibraryWin32
|
|||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
// The window the cursor is captured in
|
||||
_GLFWwindow* capturedCursorWindow;
|
||||
RAWINPUT* rawInput;
|
||||
int rawInputSize;
|
||||
UINT mouseTrailSize;
|
||||
|
@ -471,6 +478,7 @@ typedef struct _GLFWlibraryWin32
|
|||
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
||||
PFN_GetDpiForWindow GetDpiForWindow_;
|
||||
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
||||
PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_;
|
||||
} user32;
|
||||
|
||||
struct {
|
||||
|
@ -519,9 +527,6 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform);
|
|||
int _glfwInitWin32(void);
|
||||
void _glfwTerminateWin32(void);
|
||||
|
||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||
void _glfwUnregisterWindowClassWin32(void);
|
||||
|
||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
|
||||
|
@ -534,7 +539,7 @@ void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
|||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
||||
void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
|
||||
|
||||
int _glfwCreateWindowWin32(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyWindowWin32(_GLFWwindow* window);
|
||||
void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title);
|
||||
void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images);
|
||||
|
@ -555,12 +560,12 @@ void _glfwHideWindowWin32(_GLFWwindow* window);
|
|||
void _glfwRequestWindowAttentionWin32(_GLFWwindow* window);
|
||||
void _glfwFocusWindowWin32(_GLFWwindow* window);
|
||||
void _glfwSetWindowMonitorWin32(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
|
||||
int _glfwWindowFocusedWin32(_GLFWwindow* window);
|
||||
int _glfwWindowIconifiedWin32(_GLFWwindow* window);
|
||||
int _glfwWindowVisibleWin32(_GLFWwindow* window);
|
||||
int _glfwWindowMaximizedWin32(_GLFWwindow* window);
|
||||
int _glfwWindowHoveredWin32(_GLFWwindow* window);
|
||||
int _glfwFramebufferTransparentWin32(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window);
|
||||
GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window);
|
||||
void _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
@ -581,8 +586,8 @@ void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos);
|
|||
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameWin32(int scancode);
|
||||
int _glfwGetKeyScancodeWin32(int key);
|
||||
int _glfwCreateCursorWin32(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
int _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape);
|
||||
GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape);
|
||||
void _glfwDestroyCursorWin32(_GLFWcursor* cursor);
|
||||
void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
void _glfwSetClipboardStringWin32(const char* string);
|
||||
|
@ -593,7 +598,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayWin32(void);
|
|||
EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window);
|
||||
|
||||
void _glfwGetRequiredInstanceExtensionsWin32(char** extensions);
|
||||
int _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
void _glfwFreeMonitorWin32(_GLFWmonitor* monitor);
|
||||
|
@ -607,7 +612,7 @@ void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
|||
|
||||
GLFWbool _glfwInitJoysticksWin32(void);
|
||||
void _glfwTerminateJoysticksWin32(void);
|
||||
int _glfwPollJoystickWin32(_GLFWjoystick* js, int mode);
|
||||
GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode);
|
||||
const char* _glfwGetMappingNameWin32(void);
|
||||
void _glfwUpdateGamepadGUIDWin32(char* guid);
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_WIN32_THREAD)
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
|
@ -96,3 +98,5 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
|||
LeaveCriticalSection(&mutex->win32.section);
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_WIN32_THREAD
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(GLFW_BUILD_WIN32_TIMER)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
|
@ -51,3 +52,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void)
|
|||
return _glfw.timer.win32.frequency;
|
||||
}
|
||||
|
||||
#endif // GLFW_BUILD_WIN32_TIMER
|
||||
|
||||
|
|
|
@ -28,8 +28,11 @@
|
|||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "glfw3ext_internal.h" // x-studio spec
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -104,8 +107,7 @@ static const GLFWimage* chooseImage(int count, const GLFWimage* images,
|
|||
|
||||
// Creates an RGBA icon or cursor
|
||||
//
|
||||
static HICON createIcon(const GLFWimage* image,
|
||||
int xhot, int yhot, GLFWbool icon)
|
||||
static HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool icon)
|
||||
{
|
||||
int i;
|
||||
HDC dc;
|
||||
|
@ -192,53 +194,38 @@ static HICON createIcon(const GLFWimage* image,
|
|||
return handle;
|
||||
}
|
||||
|
||||
// Translate content area size to full window size according to styles and DPI
|
||||
//
|
||||
static void getFullWindowSize(DWORD style, DWORD exStyle,
|
||||
int contentWidth, int contentHeight,
|
||||
int* fullWidth, int* fullHeight,
|
||||
UINT dpi)
|
||||
{
|
||||
RECT rect = { 0, 0, contentWidth, contentHeight };
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
|
||||
else
|
||||
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||
|
||||
*fullWidth = rect.right - rect.left;
|
||||
*fullHeight = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
// Enforce the content area aspect ratio based on which edge is being dragged
|
||||
//
|
||||
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
|
||||
{
|
||||
int xoff, yoff;
|
||||
UINT dpi = USER_DEFAULT_SCREEN_DPI;
|
||||
RECT frame = {0};
|
||||
const float ratio = (float) window->numer / (float) window->denom;
|
||||
const DWORD style = getWindowStyle(window);
|
||||
const DWORD exStyle = getWindowExStyle(window);
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
dpi = GetDpiForWindow(window->win32.handle);
|
||||
|
||||
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
|
||||
0, 0, &xoff, &yoff, dpi);
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
|
||||
GetDpiForWindow(window->win32.handle));
|
||||
}
|
||||
else
|
||||
AdjustWindowRectEx(&frame, style, FALSE, exStyle);
|
||||
|
||||
if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
|
||||
edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
|
||||
{
|
||||
area->bottom = area->top + yoff +
|
||||
(int) ((area->right - area->left - xoff) / ratio);
|
||||
area->bottom = area->top + (frame.bottom - frame.top) +
|
||||
(int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
|
||||
}
|
||||
else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
|
||||
{
|
||||
area->top = area->bottom - yoff -
|
||||
(int) ((area->right - area->left - xoff) / ratio);
|
||||
area->top = area->bottom - (frame.bottom - frame.top) -
|
||||
(int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
|
||||
}
|
||||
else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
|
||||
{
|
||||
area->right = area->left + xoff +
|
||||
(int) ((area->bottom - area->top - yoff) * ratio);
|
||||
area->right = area->left + (frame.right - frame.left) +
|
||||
(int) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +233,8 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
|
|||
//
|
||||
static void updateCursorImage(_GLFWwindow* window)
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL ||
|
||||
window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
{
|
||||
if (window->cursor)
|
||||
SetCursor(window->cursor->win32.handle);
|
||||
|
@ -257,20 +245,24 @@ static void updateCursorImage(_GLFWwindow* window)
|
|||
SetCursor(NULL);
|
||||
}
|
||||
|
||||
// Updates the cursor clip rect
|
||||
// Sets the cursor clip rect to the window content area
|
||||
//
|
||||
static void updateClipRect(_GLFWwindow* window)
|
||||
static void captureCursor(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
RECT clipRect;
|
||||
GetClientRect(window->win32.handle, &clipRect);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
|
||||
ClipCursor(&clipRect);
|
||||
}
|
||||
else
|
||||
ClipCursor(NULL);
|
||||
RECT clipRect;
|
||||
GetClientRect(window->win32.handle, &clipRect);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
|
||||
ClipCursor(&clipRect);
|
||||
_glfw.win32.capturedCursorWindow = window;
|
||||
}
|
||||
|
||||
// Disabled clip cursor
|
||||
//
|
||||
static void releaseCursor(void)
|
||||
{
|
||||
ClipCursor(NULL);
|
||||
_glfw.win32.capturedCursorWindow = NULL;
|
||||
}
|
||||
|
||||
// Enables WM_INPUT messages for the mouse for the specified window
|
||||
|
@ -309,7 +301,7 @@ static void disableCursor(_GLFWwindow* window)
|
|||
&_glfw.win32.restoreCursorPosY);
|
||||
updateCursorImage(window);
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
updateClipRect(window);
|
||||
captureCursor(window);
|
||||
|
||||
if (window->rawMouseMotion)
|
||||
enableRawMouseMotion(window);
|
||||
|
@ -323,7 +315,7 @@ static void enableCursor(_GLFWwindow* window)
|
|||
disableRawMouseMotion(window);
|
||||
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
updateClipRect(NULL);
|
||||
releaseCursor();
|
||||
_glfwSetCursorPosWin32(window,
|
||||
_glfw.win32.restoreCursorPosX,
|
||||
_glfw.win32.restoreCursorPosY);
|
||||
|
@ -361,7 +353,7 @@ static void updateWindowStyles(const _GLFWwindow* window)
|
|||
|
||||
GetClientRect(window->win32.handle, &rect);
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, style, FALSE,
|
||||
getWindowExStyle(window),
|
||||
|
@ -441,7 +433,7 @@ static int getKeyMods(void)
|
|||
static void fitToMonitor(_GLFWwindow* window)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
||||
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
||||
mi.rcMonitor.left,
|
||||
mi.rcMonitor.top,
|
||||
|
@ -460,8 +452,8 @@ static void acquireMonitor(_GLFWwindow* window)
|
|||
|
||||
// HACK: When mouse trails are enabled the cursor becomes invisible when
|
||||
// the OpenGL ICD switches to page flipping
|
||||
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
||||
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
|
||||
SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
||||
SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (!window->monitor->window)
|
||||
|
@ -484,67 +476,83 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
|
||||
// HACK: Restore mouse trail length saved in acquireMonitor
|
||||
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
||||
SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
||||
}
|
||||
|
||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||
_glfwRestoreVideoModeWin32(window->monitor);
|
||||
}
|
||||
|
||||
// Window callback function (handles window messages)
|
||||
// Manually maximize the window, for when SW_MAXIMIZE cannot be used
|
||||
//
|
||||
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
static void maximizeWindowManually(_GLFWwindow* window)
|
||||
{
|
||||
RECT rect;
|
||||
DWORD style;
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
|
||||
GetMonitorInfoW(MonitorFromWindow(window->win32.handle,
|
||||
MONITOR_DEFAULTTONEAREST), &mi);
|
||||
|
||||
rect = mi.rcWork;
|
||||
|
||||
if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
|
||||
{
|
||||
rect.right = _glfw_min(rect.right, rect.left + window->maxwidth);
|
||||
rect.bottom = _glfw_min(rect.bottom, rect.top + window->maxheight);
|
||||
}
|
||||
|
||||
style = GetWindowLongW(window->win32.handle, GWL_STYLE);
|
||||
style |= WS_MAXIMIZE;
|
||||
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
|
||||
|
||||
if (window->decorated)
|
||||
{
|
||||
const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
const UINT dpi = GetDpiForWindow(window->win32.handle);
|
||||
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
|
||||
OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi));
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||
OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));
|
||||
}
|
||||
|
||||
rect.bottom = _glfw_min(rect.bottom, mi.rcWork.bottom);
|
||||
}
|
||||
|
||||
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
// Window procedure for user-created windows
|
||||
//
|
||||
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
_GLFWwindow* window = GetPropW(hWnd, L"GLFW");
|
||||
if (!window)
|
||||
{
|
||||
// This is the message handling for the hidden helper window
|
||||
// and for a regular window during its initial creation
|
||||
|
||||
switch (uMsg)
|
||||
if (uMsg == WM_NCCREATE)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
{
|
||||
const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;
|
||||
const _GLFWwndconfig* wndconfig = cs->lpCreateParams;
|
||||
const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;
|
||||
const _GLFWwndconfig* wndconfig = cs->lpCreateParams;
|
||||
|
||||
// On per-monitor DPI aware V1 systems, only enable
|
||||
// non-client scaling for windows that scale the client area
|
||||
// We need WM_GETDPISCALEDSIZE from V2 to keep the client
|
||||
// area static when the non-client area is scaled
|
||||
if (wndconfig && wndconfig->scaleToMonitor)
|
||||
EnableNonClientDpiScaling(hWnd);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DISPLAYCHANGE:
|
||||
_glfwPollMonitorsWin32();
|
||||
break;
|
||||
|
||||
case WM_DEVICECHANGE:
|
||||
{
|
||||
if (!_glfw.joysticksInitialized)
|
||||
break;
|
||||
|
||||
if (wParam == DBT_DEVICEARRIVAL)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickConnectionWin32();
|
||||
}
|
||||
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickDisconnectionWin32();
|
||||
}
|
||||
|
||||
break;
|
||||
// On per-monitor DPI aware V1 systems, only enable
|
||||
// non-client scaling for windows that scale the client area
|
||||
// We need WM_GETDPISCALEDSIZE from V2 to keep the client
|
||||
// area static when the non-client area is scaled
|
||||
if (wndconfig && wndconfig->scaleToMonitor)
|
||||
EnableNonClientDpiScaling(hWnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,6 +582,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
disableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
captureCursor(window);
|
||||
|
||||
window->win32.frameAction = GLFW_FALSE;
|
||||
}
|
||||
|
@ -592,6 +602,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
disableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
captureCursor(window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -600,6 +612,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
enableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
releaseCursor();
|
||||
|
||||
if (window->monitor && window->autoIconify)
|
||||
_glfwIconifyWindowWin32(window);
|
||||
|
@ -711,6 +725,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
|
||||
}
|
||||
|
||||
// HACK: Alt+PrtSc has a different scancode than just PrtSc
|
||||
if (scancode == 0x54)
|
||||
scancode = 0x137;
|
||||
|
||||
// HACK: Ctrl+Pause has a different scancode than just Pause
|
||||
if (scancode == 0x146)
|
||||
scancode = 0x45;
|
||||
|
||||
// HACK: CJK IME sets the extended bit for right Shift
|
||||
if (scancode == 0x136)
|
||||
scancode = 0x36;
|
||||
|
||||
key = _glfw.win32.keycodes[scancode];
|
||||
|
||||
// The Ctrl keys require special handling
|
||||
|
@ -962,6 +988,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
// resizing the window or using the window menu
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
enableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
releaseCursor();
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -976,6 +1004,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
// resizing the window or using the menu
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
disableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
captureCursor(window);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -989,8 +1019,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
(window->win32.maximized &&
|
||||
wParam != SIZE_RESTORED);
|
||||
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
updateClipRect(window);
|
||||
if (_glfw.win32.capturedCursorWindow == window)
|
||||
captureCursor(window);
|
||||
|
||||
if (window->win32.iconified != iconified)
|
||||
_glfwInputWindowIconify(window, iconified);
|
||||
|
@ -1025,8 +1055,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
|
||||
case WM_MOVE:
|
||||
{
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
updateClipRect(window);
|
||||
if (_glfw.win32.capturedCursorWindow == window)
|
||||
captureCursor(window);
|
||||
|
||||
// NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
|
||||
// those macros do not handle negative window positions correctly
|
||||
|
@ -1050,31 +1080,34 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
int xoff, yoff;
|
||||
UINT dpi = USER_DEFAULT_SCREEN_DPI;
|
||||
RECT frame = {0};
|
||||
MINMAXINFO* mmi = (MINMAXINFO*) lParam;
|
||||
const DWORD style = getWindowStyle(window);
|
||||
const DWORD exStyle = getWindowExStyle(window);
|
||||
|
||||
if (window->monitor)
|
||||
break;
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
dpi = GetDpiForWindow(window->win32.handle);
|
||||
|
||||
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
|
||||
0, 0, &xoff, &yoff, dpi);
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
|
||||
GetDpiForWindow(window->win32.handle));
|
||||
}
|
||||
else
|
||||
AdjustWindowRectEx(&frame, style, FALSE, exStyle);
|
||||
|
||||
if (window->minwidth != GLFW_DONT_CARE &&
|
||||
window->minheight != GLFW_DONT_CARE)
|
||||
{
|
||||
mmi->ptMinTrackSize.x = window->minwidth + xoff;
|
||||
mmi->ptMinTrackSize.y = window->minheight + yoff;
|
||||
mmi->ptMinTrackSize.x = window->minwidth + frame.right - frame.left;
|
||||
mmi->ptMinTrackSize.y = window->minheight + frame.bottom - frame.top;
|
||||
}
|
||||
|
||||
if (window->maxwidth != GLFW_DONT_CARE &&
|
||||
window->maxheight != GLFW_DONT_CARE)
|
||||
{
|
||||
mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
|
||||
mmi->ptMaxTrackSize.y = window->maxheight + yoff;
|
||||
mmi->ptMaxTrackSize.x = window->maxwidth + frame.right - frame.left;
|
||||
mmi->ptMaxTrackSize.y = window->maxheight + frame.bottom - frame.top;
|
||||
}
|
||||
|
||||
if (!window->decorated)
|
||||
|
@ -1085,7 +1118,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
|
||||
ZeroMemory(&mi, sizeof(mi));
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(mh, &mi);
|
||||
GetMonitorInfoW(mh, &mi);
|
||||
|
||||
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
|
||||
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
|
||||
|
@ -1132,7 +1165,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
break;
|
||||
|
||||
// Adjust the window size to keep the content area size constant
|
||||
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1703OrGreaterWin32())
|
||||
{
|
||||
RECT source = {0}, target = {0};
|
||||
SIZE* size = (SIZE*) lParam;
|
||||
|
@ -1163,7 +1196,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||
// need it to compensate for non-client area scaling
|
||||
if (!window->monitor &&
|
||||
(window->win32.scaleToMonitor ||
|
||||
_glfwIsWindows10CreatorsUpdateOrGreaterWin32()))
|
||||
_glfwIsWindows10Version1703OrGreaterWin32()))
|
||||
{
|
||||
RECT* suggested = (RECT*) lParam;
|
||||
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||
|
@ -1233,36 +1266,80 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
int xpos, ypos, fullWidth, fullHeight;
|
||||
int frameX, frameY, frameWidth, frameHeight;
|
||||
WCHAR* wideTitle;
|
||||
DWORD style = getWindowStyle(window);
|
||||
DWORD exStyle = getWindowExStyle(window);
|
||||
|
||||
if (!_glfw.win32.mainWindowClass)
|
||||
{
|
||||
WNDCLASSEXW wc = { sizeof(wc) };
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wc.lpfnWndProc = windowProc;
|
||||
wc.hInstance = _glfw.win32.instance;
|
||||
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
||||
#if defined(_GLFW_WNDCLASSNAME)
|
||||
wc.lpszClassName = _GLFW_WNDCLASSNAME;
|
||||
#else
|
||||
wc.lpszClassName = L"GLFW30";
|
||||
#endif
|
||||
// Load user-provided icon if available
|
||||
wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
|
||||
L"GLFW_ICON", IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
if (!wc.hIcon)
|
||||
{
|
||||
// No user-provided icon found, load default icon
|
||||
wc.hIcon = LoadImageW(NULL,
|
||||
IDI_APPLICATION, IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
}
|
||||
|
||||
_glfw.win32.mainWindowClass = RegisterClassExW(&wc);
|
||||
if (!_glfw.win32.mainWindowClass)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to register window class");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
GLFWvidmode mode;
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||
|
||||
// NOTE: This window placement is temporary and approximate, as the
|
||||
// correct position and size cannot be known until the monitor
|
||||
// video mode has been picked in _glfwSetVideoModeWin32
|
||||
_glfwGetMonitorPosWin32(window->monitor, &xpos, &ypos);
|
||||
_glfwGetVideoModeWin32(window->monitor, &mode);
|
||||
fullWidth = mode.width;
|
||||
fullHeight = mode.height;
|
||||
frameX = mi.rcMonitor.left;
|
||||
frameY = mi.rcMonitor.top;
|
||||
frameWidth = mi.rcMonitor.right - mi.rcMonitor.left;
|
||||
frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top;
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = CW_USEDEFAULT;
|
||||
ypos = CW_USEDEFAULT;
|
||||
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
|
||||
|
||||
window->win32.maximized = wndconfig->maximized;
|
||||
if (wndconfig->maximized)
|
||||
style |= WS_MAXIMIZE;
|
||||
|
||||
getFullWindowSize(style, exStyle,
|
||||
wndconfig->width, wndconfig->height,
|
||||
&fullWidth, &fullHeight,
|
||||
USER_DEFAULT_SCREEN_DPI);
|
||||
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||
|
||||
if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION)
|
||||
{
|
||||
frameX = CW_USEDEFAULT;
|
||||
frameY = CW_USEDEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
frameX = wndconfig->xpos + rect.left;
|
||||
frameY = wndconfig->ypos + rect.top;
|
||||
}
|
||||
|
||||
frameWidth = rect.right - rect.left;
|
||||
frameHeight = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
|
||||
|
@ -1270,14 +1347,14 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
return GLFW_FALSE;
|
||||
|
||||
window->win32.handle = CreateWindowExW(exStyle,
|
||||
_GLFW_WNDCLASSNAME,
|
||||
MAKEINTATOM(_glfw.win32.mainWindowClass),
|
||||
wideTitle,
|
||||
style,
|
||||
xpos, ypos,
|
||||
fullWidth, fullHeight,
|
||||
frameX, frameY,
|
||||
frameWidth, frameHeight,
|
||||
_glfwx.hwndGLParent, // x-studio spec, create as child window support.
|
||||
NULL, // No window menu
|
||||
GetModuleHandleW(NULL),
|
||||
_glfw.win32.instance,
|
||||
(LPVOID) wndconfig);
|
||||
|
||||
_glfw_free(wideTitle);
|
||||
|
@ -1304,18 +1381,22 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
|
||||
window->win32.keymenu = wndconfig->win32.keymenu;
|
||||
|
||||
// Adjust window rect to account for DPI scaling of the window frame and
|
||||
// (if enabled) DPI scaling of the content area
|
||||
// This cannot be done until we know what monitor the window was placed on
|
||||
if (!window->monitor)
|
||||
{
|
||||
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
|
||||
WINDOWPLACEMENT wp = { sizeof(wp) };
|
||||
const HMONITOR mh = MonitorFromWindow(window->win32.handle,
|
||||
MONITOR_DEFAULTTONEAREST);
|
||||
|
||||
// Adjust window rect to account for DPI scaling of the window frame and
|
||||
// (if enabled) DPI scaling of the content area
|
||||
// This cannot be done until we know what monitor the window was placed on
|
||||
// Only update the restored window rect as the window may be maximized
|
||||
|
||||
if (wndconfig->scaleToMonitor)
|
||||
{
|
||||
float xscale, yscale;
|
||||
_glfwGetWindowContentScaleWin32(window, &xscale, &yscale);
|
||||
_glfwGetHMONITORContentScaleWin32(mh, &xscale, &yscale);
|
||||
|
||||
if (xscale > 0.f && yscale > 0.f)
|
||||
{
|
||||
|
@ -1324,10 +1405,7 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
}
|
||||
}
|
||||
|
||||
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
|
||||
GetDpiForWindow(window->win32.handle));
|
||||
|
@ -1335,11 +1413,30 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
else
|
||||
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||
|
||||
// Only update the restored window rect as the window may be maximized
|
||||
GetWindowPlacement(window->win32.handle, &wp);
|
||||
OffsetRect(&rect,
|
||||
wp.rcNormalPosition.left - rect.left,
|
||||
wp.rcNormalPosition.top - rect.top);
|
||||
|
||||
wp.rcNormalPosition = rect;
|
||||
wp.showCmd = SW_HIDE;
|
||||
SetWindowPlacement(window->win32.handle, &wp);
|
||||
|
||||
// Adjust rect of maximized undecorated window, because by default Windows will
|
||||
// make such a window cover the whole monitor instead of its workarea
|
||||
|
||||
if (wndconfig->maximized && !wndconfig->decorated)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
GetMonitorInfoW(mh, &mi);
|
||||
|
||||
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||
mi.rcWork.left,
|
||||
mi.rcWork.top,
|
||||
mi.rcWork.right - mi.rcWork.left,
|
||||
mi.rcWork.bottom - mi.rcWork.top,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER);
|
||||
}
|
||||
}
|
||||
|
||||
DragAcceptFiles(window->win32.handle, TRUE);
|
||||
|
@ -1355,53 +1452,10 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Registers the GLFW window class
|
||||
//
|
||||
GLFWbool _glfwRegisterWindowClassWin32(void)
|
||||
{
|
||||
WNDCLASSEXW wc;
|
||||
|
||||
ZeroMemory(&wc, sizeof(wc));
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wc.lpfnWndProc = (WNDPROC) windowProc;
|
||||
wc.hInstance = GetModuleHandleW(NULL);
|
||||
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
||||
wc.lpszClassName = _GLFW_WNDCLASSNAME;
|
||||
|
||||
// Load user-provided icon if available
|
||||
wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
|
||||
L"GLFW_ICON", IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
if (!wc.hIcon)
|
||||
{
|
||||
// No user-provided icon found, load default icon
|
||||
wc.hIcon = LoadImageW(NULL,
|
||||
IDI_APPLICATION, IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
}
|
||||
|
||||
if (!RegisterClassExW(&wc))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to register window class");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Unregisters the GLFW window class
|
||||
//
|
||||
void _glfwUnregisterWindowClassWin32(void)
|
||||
{
|
||||
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
|
||||
}
|
||||
|
||||
int _glfwCreateWindowWin32(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
@ -1429,14 +1483,32 @@ int _glfwCreateWindowWin32(_GLFWwindow* window,
|
|||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwRefreshContextAttribs(window, ctxconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (wndconfig->mousePassthrough)
|
||||
_glfwSetWindowMousePassthroughWin32(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
_glfwShowWindowWin32(window);
|
||||
_glfwFocusWindowWin32(window);
|
||||
acquireMonitor(window);
|
||||
fitToMonitor(window);
|
||||
|
||||
if (wndconfig->centerCursor)
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
_glfwShowWindowWin32(window);
|
||||
if (wndconfig->focused)
|
||||
_glfwFocusWindowWin32(window);
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
@ -1451,7 +1523,10 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window)
|
|||
window->context.destroy(window);
|
||||
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
enableCursor(window);
|
||||
|
||||
if (_glfw.win32.capturedCursorWindow == window)
|
||||
releaseCursor();
|
||||
|
||||
if (window->win32.handle)
|
||||
{
|
||||
|
@ -1477,8 +1552,7 @@ void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title)
|
|||
_glfw_free(wideTitle);
|
||||
}
|
||||
|
||||
void _glfwSetWindowIconWin32(_GLFWwindow* window,
|
||||
int count, const GLFWimage* images)
|
||||
void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images)
|
||||
{
|
||||
HICON bigIcon = NULL, smallIcon = NULL;
|
||||
|
||||
|
@ -1500,8 +1574,8 @@ void _glfwSetWindowIconWin32(_GLFWwindow* window,
|
|||
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
|
||||
}
|
||||
|
||||
SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
||||
SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
||||
SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
||||
SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
||||
|
||||
if (window->win32.bigIcon)
|
||||
DestroyIcon(window->win32.bigIcon);
|
||||
|
@ -1531,7 +1605,7 @@ void _glfwSetWindowPosWin32(_GLFWwindow* window, int xpos, int ypos)
|
|||
{
|
||||
RECT rect = { xpos, ypos, xpos, ypos };
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
|
||||
FALSE, getWindowExStyle(window),
|
||||
|
@ -1572,7 +1646,7 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
|
|||
{
|
||||
RECT rect = { 0, 0, width, height };
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
|
||||
FALSE, getWindowExStyle(window),
|
||||
|
@ -1591,8 +1665,8 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
|
|||
}
|
||||
|
||||
void _glfwSetWindowSizeLimitsWin32(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
RECT area;
|
||||
|
||||
|
@ -1630,8 +1704,8 @@ void _glfwGetFramebufferSizeWin32(_GLFWwindow* window, int* width, int* height)
|
|||
}
|
||||
|
||||
void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
RECT rect;
|
||||
int width, height;
|
||||
|
@ -1639,7 +1713,7 @@ void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
|
|||
_glfwGetWindowSizeWin32(window, &width, &height);
|
||||
SetRect(&rect, 0, 0, width, height);
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
|
||||
FALSE, getWindowExStyle(window),
|
||||
|
@ -1680,7 +1754,10 @@ void _glfwRestoreWindowWin32(_GLFWwindow* window)
|
|||
|
||||
void _glfwMaximizeWindowWin32(_GLFWwindow* window)
|
||||
{
|
||||
ShowWindow(window->win32.handle, SW_MAXIMIZE);
|
||||
if (IsWindowVisible(window->win32.handle))
|
||||
ShowWindow(window->win32.handle, SW_MAXIMIZE);
|
||||
else
|
||||
maximizeWindowManually(window);
|
||||
}
|
||||
|
||||
void _glfwShowWindowWin32(_GLFWwindow* window)
|
||||
|
@ -1725,7 +1802,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
|
|||
{
|
||||
RECT rect = { xpos, ypos, xpos + width, ypos + height };
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
|
||||
FALSE, getWindowExStyle(window),
|
||||
|
@ -1767,7 +1844,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
|
|||
|
||||
acquireMonitor(window);
|
||||
|
||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
||||
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
||||
mi.rcMonitor.left,
|
||||
mi.rcMonitor.top,
|
||||
|
@ -1796,7 +1873,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
|
|||
else
|
||||
after = HWND_NOTOPMOST;
|
||||
|
||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||
if (_glfwIsWindows10Version1607OrGreaterWin32())
|
||||
{
|
||||
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
|
||||
FALSE, getWindowExStyle(window),
|
||||
|
@ -1815,32 +1892,32 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
|
|||
}
|
||||
}
|
||||
|
||||
int _glfwWindowFocusedWin32(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window)
|
||||
{
|
||||
return window->win32.handle == GetActiveWindow();
|
||||
}
|
||||
|
||||
int _glfwWindowIconifiedWin32(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window)
|
||||
{
|
||||
return IsIconic(window->win32.handle);
|
||||
}
|
||||
|
||||
int _glfwWindowVisibleWin32(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window)
|
||||
{
|
||||
return IsWindowVisible(window->win32.handle);
|
||||
}
|
||||
|
||||
int _glfwWindowMaximizedWin32(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window)
|
||||
{
|
||||
return IsZoomed(window->win32.handle);
|
||||
}
|
||||
|
||||
int _glfwWindowHoveredWin32(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window)
|
||||
{
|
||||
return cursorInContentArea(window);
|
||||
}
|
||||
|
||||
int _glfwFramebufferTransparentWin32(_GLFWwindow* window)
|
||||
GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window)
|
||||
{
|
||||
BOOL composition, opaque;
|
||||
DWORD color;
|
||||
|
@ -2064,7 +2141,7 @@ void _glfwWaitEventsTimeoutWin32(double timeout)
|
|||
|
||||
void _glfwPostEmptyEventWin32(void)
|
||||
{
|
||||
PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
||||
PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
||||
}
|
||||
|
||||
void _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
|
@ -2096,14 +2173,40 @@ void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos)
|
|||
|
||||
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode)
|
||||
{
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
if (_glfwWindowFocusedWin32(window))
|
||||
{
|
||||
if (_glfwWindowFocusedWin32(window))
|
||||
disableCursor(window);
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfwGetCursorPosWin32(window,
|
||||
&_glfw.win32.restoreCursorPosX,
|
||||
&_glfw.win32.restoreCursorPosY);
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
if (window->rawMouseMotion)
|
||||
enableRawMouseMotion(window);
|
||||
}
|
||||
else if (_glfw.win32.disabledCursorWindow == window)
|
||||
{
|
||||
if (window->rawMouseMotion)
|
||||
disableRawMouseMotion(window);
|
||||
}
|
||||
|
||||
if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED)
|
||||
captureCursor(window);
|
||||
else
|
||||
releaseCursor();
|
||||
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
_glfw.win32.disabledCursorWindow = window;
|
||||
else if (_glfw.win32.disabledCursorWindow == window)
|
||||
{
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
_glfwSetCursorPosWin32(window,
|
||||
_glfw.win32.restoreCursorPosX,
|
||||
_glfw.win32.restoreCursorPosY);
|
||||
}
|
||||
}
|
||||
else if (_glfw.win32.disabledCursorWindow == window)
|
||||
enableCursor(window);
|
||||
else if (cursorInContentArea(window))
|
||||
|
||||
if (cursorInContentArea(window))
|
||||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
|
@ -2124,9 +2227,9 @@ int _glfwGetKeyScancodeWin32(int key)
|
|||
return _glfw.win32.scancodes[key];
|
||||
}
|
||||
|
||||
int _glfwCreateCursorWin32(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
|
||||
if (!cursor->win32.handle)
|
||||
|
@ -2135,7 +2238,7 @@ int _glfwCreateCursorWin32(_GLFWcursor* cursor,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
int _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape)
|
||||
GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
|
@ -2343,9 +2446,9 @@ void _glfwGetRequiredInstanceExtensionsWin32(char** extensions)
|
|||
extensions[1] = "VK_KHR_win32_surface";
|
||||
}
|
||||
|
||||
int _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
|
||||
vkGetPhysicalDeviceWin32PresentationSupportKHR =
|
||||
|
@ -2381,7 +2484,7 @@ VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance,
|
|||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||
sci.hinstance = GetModuleHandle(NULL);
|
||||
sci.hinstance = _glfw.win32.instance;
|
||||
sci.hwnd = window->win32.handle;
|
||||
|
||||
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
|
||||
|
@ -2410,3 +2513,5 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
|
|||
return window->win32.handle;
|
||||
}
|
||||
|
||||
#endif // _GLFW_WIN32
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
//
|
||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(focused == GLFW_TRUE || focused == GLFW_FALSE);
|
||||
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
|
||||
|
@ -73,6 +76,8 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
|||
//
|
||||
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
||||
{
|
||||
assert(window != NULL);
|
||||
|
||||
if (window->callbacks.pos)
|
||||
window->callbacks.pos((GLFWwindow*) window, x, y);
|
||||
}
|
||||
|
@ -82,6 +87,10 @@ void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
|||
//
|
||||
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
if (window->callbacks.size)
|
||||
window->callbacks.size((GLFWwindow*) window, width, height);
|
||||
}
|
||||
|
@ -90,6 +99,9 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
|||
//
|
||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(iconified == GLFW_TRUE || iconified == GLFW_FALSE);
|
||||
|
||||
if (window->callbacks.iconify)
|
||||
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
||||
}
|
||||
|
@ -98,6 +110,9 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
|||
//
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(maximized == GLFW_TRUE || maximized == GLFW_FALSE);
|
||||
|
||||
if (window->callbacks.maximize)
|
||||
window->callbacks.maximize((GLFWwindow*) window, maximized);
|
||||
}
|
||||
|
@ -107,6 +122,10 @@ void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
|||
//
|
||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
if (window->callbacks.fbsize)
|
||||
window->callbacks.fbsize((GLFWwindow*) window, width, height);
|
||||
}
|
||||
|
@ -116,6 +135,12 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
|||
//
|
||||
void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
|
||||
{
|
||||
assert(window != NULL);
|
||||
assert(xscale > 0.f);
|
||||
assert(xscale < FLT_MAX);
|
||||
assert(yscale > 0.f);
|
||||
assert(yscale < FLT_MAX);
|
||||
|
||||
if (window->callbacks.scale)
|
||||
window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
|
||||
}
|
||||
|
@ -124,6 +149,8 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal
|
|||
//
|
||||
void _glfwInputWindowDamage(_GLFWwindow* window)
|
||||
{
|
||||
assert(window != NULL);
|
||||
|
||||
if (window->callbacks.refresh)
|
||||
window->callbacks.refresh((GLFWwindow*) window);
|
||||
}
|
||||
|
@ -132,6 +159,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window)
|
|||
//
|
||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
||||
{
|
||||
assert(window != NULL);
|
||||
|
||||
window->shouldClose = GLFW_TRUE;
|
||||
|
||||
if (window->callbacks.close)
|
||||
|
@ -142,6 +171,7 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
|||
//
|
||||
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
|
||||
{
|
||||
assert(window != NULL);
|
||||
window->monitor = monitor;
|
||||
}
|
||||
|
||||
|
@ -215,40 +245,12 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||
window->numer = GLFW_DONT_CARE;
|
||||
window->denom = GLFW_DONT_CARE;
|
||||
|
||||
// Open the actual window and create its context
|
||||
if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig))
|
||||
{
|
||||
glfwDestroyWindow((GLFWwindow*) window);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctxconfig.client != GLFW_NO_API)
|
||||
{
|
||||
if (!_glfwRefreshContextAttribs(window, &ctxconfig))
|
||||
{
|
||||
glfwDestroyWindow((GLFWwindow*) window);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (wndconfig.mousePassthrough)
|
||||
_glfw.platform.setWindowMousePassthrough(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
if (wndconfig.centerCursor)
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wndconfig.visible)
|
||||
{
|
||||
_glfw.platform.showWindow(window);
|
||||
if (wndconfig.focused)
|
||||
_glfw.platform.focusWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
return (GLFWwindow*) window;
|
||||
}
|
||||
|
||||
|
@ -272,6 +274,8 @@ void glfwDefaultWindowHints(void)
|
|||
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
||||
_glfw.hints.window.centerCursor = GLFW_TRUE;
|
||||
_glfw.hints.window.focusOnShow = GLFW_TRUE;
|
||||
_glfw.hints.window.xpos = GLFW_ANY_POSITION;
|
||||
_glfw.hints.window.ypos = GLFW_ANY_POSITION;
|
||||
|
||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||
// double buffered
|
||||
|
@ -366,6 +370,12 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
|||
case GLFW_VISIBLE:
|
||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_POSITION_X:
|
||||
_glfw.hints.window.xpos = value;
|
||||
return;
|
||||
case GLFW_POSITION_Y:
|
||||
_glfw.hints.window.ypos = value;
|
||||
return;
|
||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
|
@ -445,6 +455,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value)
|
|||
strncpy(_glfw.hints.window.x11.instanceName, value,
|
||||
sizeof(_glfw.hints.window.x11.instanceName) - 1);
|
||||
return;
|
||||
case GLFW_WAYLAND_APP_ID:
|
||||
strncpy(_glfw.hints.window.wl.appId, value,
|
||||
sizeof(_glfw.hints.window.wl.appId) - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
|
||||
|
@ -514,12 +528,33 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
|
|||
GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
|
||||
int count, const GLFWimage* images)
|
||||
{
|
||||
int i;
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
|
||||
assert(window != NULL);
|
||||
assert(count >= 0);
|
||||
assert(count == 0 || images != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
assert(images[i].pixels != NULL);
|
||||
|
||||
if (images[i].width <= 0 || images[i].height <= 0)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"Invalid image dimensions for window icon");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.platform.setWindowIcon(window, count, images);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_WAYLAND)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -37,7 +39,7 @@
|
|||
#include "wayland-client-protocol.h"
|
||||
|
||||
|
||||
static void outputHandleGeometry(void* data,
|
||||
static void outputHandleGeometry(void* userData,
|
||||
struct wl_output* output,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
|
@ -48,24 +50,25 @@ static void outputHandleGeometry(void* data,
|
|||
const char* model,
|
||||
int32_t transform)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
struct _GLFWmonitor* monitor = userData;
|
||||
|
||||
monitor->wl.x = x;
|
||||
monitor->wl.y = y;
|
||||
monitor->widthMM = physicalWidth;
|
||||
monitor->heightMM = physicalHeight;
|
||||
|
||||
snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model);
|
||||
if (strlen(monitor->name) == 0)
|
||||
snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model);
|
||||
}
|
||||
|
||||
static void outputHandleMode(void* data,
|
||||
static void outputHandleMode(void* userData,
|
||||
struct wl_output* output,
|
||||
uint32_t flags,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int32_t refresh)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
struct _GLFWmonitor* monitor = userData;
|
||||
GLFWvidmode mode;
|
||||
|
||||
mode.width = width;
|
||||
|
@ -84,9 +87,9 @@ static void outputHandleMode(void* data,
|
|||
monitor->wl.currentMode = monitor->modeCount - 1;
|
||||
}
|
||||
|
||||
static void outputHandleDone(void* data, struct wl_output* output)
|
||||
static void outputHandleDone(void* userData, struct wl_output* output)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
struct _GLFWmonitor* monitor = userData;
|
||||
|
||||
if (monitor->widthMM <= 0 || monitor->heightMM <= 0)
|
||||
{
|
||||
|
@ -96,23 +99,63 @@ static void outputHandleDone(void* data, struct wl_output* output)
|
|||
monitor->heightMM = (int) (mode->height * 25.4f / 96.f);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _glfw.monitorCount; i++)
|
||||
{
|
||||
if (_glfw.monitors[i] == monitor)
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
|
||||
static void outputHandleScale(void* data,
|
||||
static void outputHandleScale(void* userData,
|
||||
struct wl_output* output,
|
||||
int32_t factor)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
struct _GLFWmonitor* monitor = userData;
|
||||
|
||||
monitor->wl.scale = factor;
|
||||
|
||||
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
|
||||
{
|
||||
for (int i = 0; i < window->wl.monitorsCount; i++)
|
||||
{
|
||||
if (window->wl.monitors[i] == monitor)
|
||||
{
|
||||
_glfwUpdateContentScaleWayland(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_output_listener outputListener = {
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
|
||||
void outputHandleName(void* userData, struct wl_output* wl_output, const char* name)
|
||||
{
|
||||
struct _GLFWmonitor* monitor = userData;
|
||||
|
||||
strncpy(monitor->name, name, sizeof(monitor->name) - 1);
|
||||
}
|
||||
|
||||
void outputHandleDescription(void* userData,
|
||||
struct wl_output* wl_output,
|
||||
const char* description)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // WL_OUTPUT_NAME_SINCE_VERSION
|
||||
|
||||
static const struct wl_output_listener outputListener =
|
||||
{
|
||||
outputHandleGeometry,
|
||||
outputHandleMode,
|
||||
outputHandleDone,
|
||||
outputHandleScale,
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
outputHandleName,
|
||||
outputHandleDescription,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -122,9 +165,6 @@ static const struct wl_output_listener outputListener = {
|
|||
|
||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||
{
|
||||
_GLFWmonitor *monitor;
|
||||
struct wl_output *output;
|
||||
|
||||
if (version < 2)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
|
@ -132,19 +172,21 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
|||
return;
|
||||
}
|
||||
|
||||
// The actual name of this output will be set in the geometry handler.
|
||||
monitor = _glfwAllocMonitor("", 0, 0);
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION);
|
||||
#else
|
||||
version = 2;
|
||||
#endif
|
||||
|
||||
output = wl_registry_bind(_glfw.wl.registry,
|
||||
name,
|
||||
&wl_output_interface,
|
||||
2);
|
||||
struct wl_output* output = wl_registry_bind(_glfw.wl.registry,
|
||||
name,
|
||||
&wl_output_interface,
|
||||
version);
|
||||
if (!output)
|
||||
{
|
||||
_glfwFreeMonitor(monitor);
|
||||
return;
|
||||
}
|
||||
|
||||
// The actual name of this output will be set in the geometry handler
|
||||
_GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
|
||||
monitor->wl.scale = 1;
|
||||
monitor->wl.output = output;
|
||||
monitor->wl.name = name;
|
||||
|
@ -230,3 +272,5 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
|
|||
return monitor->wl.output;
|
||||
}
|
||||
|
||||
#endif // _GLFW_WAYLAND
|
||||
|
||||
|
|
|
@ -43,11 +43,12 @@ typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWa
|
|||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||
|
||||
#include "xkb_unicode.h"
|
||||
#include "posix_poll.h"
|
||||
|
||||
typedef int (* PFN_wl_display_flush)(struct wl_display *display);
|
||||
typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display);
|
||||
typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display *display);
|
||||
typedef int (* PFN_wl_display_read_events)(struct wl_display *display);
|
||||
typedef int (* PFN_wl_display_flush)(struct wl_display* display);
|
||||
typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display);
|
||||
typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display);
|
||||
typedef int (* PFN_wl_display_read_events)(struct wl_display* display);
|
||||
typedef struct wl_display* (* PFN_wl_display_connect)(const char*);
|
||||
typedef void (* PFN_wl_display_disconnect)(struct wl_display*);
|
||||
typedef int (* PFN_wl_display_roundtrip)(struct wl_display*);
|
||||
|
@ -166,8 +167,8 @@ typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
|||
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
||||
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
||||
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
||||
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
||||
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
|
||||
typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component);
|
||||
#define xkb_context_new _glfw.wl.xkb.context_new
|
||||
#define xkb_context_unref _glfw.wl.xkb.context_unref
|
||||
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
||||
|
@ -179,8 +180,8 @@ typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xk
|
|||
#define xkb_state_unref _glfw.wl.xkb.state_unref
|
||||
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
|
||||
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
|
||||
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
|
||||
#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
|
||||
#define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active
|
||||
|
||||
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
||||
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
||||
|
@ -197,11 +198,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
|
|||
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
||||
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
||||
|
||||
#define _GLFW_DECORATION_WIDTH 4
|
||||
#define _GLFW_DECORATION_TOP 24
|
||||
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
|
||||
#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
|
||||
|
||||
typedef enum _GLFWdecorationSideWayland
|
||||
{
|
||||
mainWindow,
|
||||
|
@ -218,6 +214,13 @@ typedef struct _GLFWdecorationWayland
|
|||
struct wp_viewport* viewport;
|
||||
} _GLFWdecorationWayland;
|
||||
|
||||
typedef struct _GLFWofferWayland
|
||||
{
|
||||
struct wl_data_offer* offer;
|
||||
GLFWbool text_plain_utf8;
|
||||
GLFWbool text_uri_list;
|
||||
} _GLFWofferWayland;
|
||||
|
||||
// Wayland-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowWayland
|
||||
|
@ -225,22 +228,37 @@ typedef struct _GLFWwindowWayland
|
|||
int width, height;
|
||||
GLFWbool visible;
|
||||
GLFWbool maximized;
|
||||
GLFWbool activated;
|
||||
GLFWbool fullscreen;
|
||||
GLFWbool hovered;
|
||||
GLFWbool transparent;
|
||||
struct wl_surface* surface;
|
||||
struct wl_egl_window* native;
|
||||
struct wl_callback* callback;
|
||||
|
||||
struct {
|
||||
struct wl_egl_window* window;
|
||||
} egl;
|
||||
|
||||
struct {
|
||||
int width, height;
|
||||
GLFWbool maximized;
|
||||
GLFWbool iconified;
|
||||
GLFWbool activated;
|
||||
GLFWbool fullscreen;
|
||||
} pending;
|
||||
|
||||
struct {
|
||||
struct xdg_surface* surface;
|
||||
struct xdg_toplevel* toplevel;
|
||||
struct zxdg_toplevel_decoration_v1* decoration;
|
||||
uint32_t decorationMode;
|
||||
} xdg;
|
||||
|
||||
_GLFWcursor* currentCursor;
|
||||
double cursorPosX, cursorPosY;
|
||||
|
||||
char* title;
|
||||
char* appId;
|
||||
|
||||
// We need to track the monitors the window spans on to calculate the
|
||||
// optimal scaling factor.
|
||||
|
@ -249,20 +267,16 @@ typedef struct _GLFWwindowWayland
|
|||
int monitorsCount;
|
||||
int monitorsSize;
|
||||
|
||||
struct {
|
||||
struct zwp_relative_pointer_v1* relativePointer;
|
||||
struct zwp_locked_pointer_v1* lockedPointer;
|
||||
} pointerLock;
|
||||
struct zwp_relative_pointer_v1* relativePointer;
|
||||
struct zwp_locked_pointer_v1* lockedPointer;
|
||||
struct zwp_confined_pointer_v1* confinedPointer;
|
||||
|
||||
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||
|
||||
GLFWbool wasFullscreen;
|
||||
|
||||
struct {
|
||||
GLFWbool serverSide;
|
||||
struct wl_buffer* buffer;
|
||||
_GLFWdecorationWayland top, left, right, bottom;
|
||||
int focus;
|
||||
_GLFWdecorationSideWayland focus;
|
||||
} decorations;
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
|
@ -280,8 +294,6 @@ typedef struct _GLFWlibraryWayland
|
|||
struct wl_keyboard* keyboard;
|
||||
struct wl_data_device_manager* dataDeviceManager;
|
||||
struct wl_data_device* dataDevice;
|
||||
struct wl_data_offer* dataOffer;
|
||||
struct wl_data_source* dataSource;
|
||||
struct xdg_wm_base* wmBase;
|
||||
struct zxdg_decoration_manager_v1* decorationManager;
|
||||
struct wp_viewporter* viewporter;
|
||||
|
@ -289,6 +301,16 @@ typedef struct _GLFWlibraryWayland
|
|||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
|
||||
|
||||
_GLFWofferWayland* offers;
|
||||
unsigned int offerCount;
|
||||
|
||||
struct wl_data_offer* selectionOffer;
|
||||
struct wl_data_source* selectionSource;
|
||||
|
||||
struct wl_data_offer* dragOffer;
|
||||
_GLFWwindow* dragFocus;
|
||||
uint32_t dragSerial;
|
||||
|
||||
int compositorVersion;
|
||||
int seatVersion;
|
||||
|
||||
|
@ -300,15 +322,12 @@ typedef struct _GLFWlibraryWayland
|
|||
uint32_t serial;
|
||||
uint32_t pointerEnterSerial;
|
||||
|
||||
int32_t keyboardRepeatRate;
|
||||
int32_t keyboardRepeatDelay;
|
||||
int keyboardLastKey;
|
||||
int keyboardLastScancode;
|
||||
int keyRepeatTimerfd;
|
||||
int32_t keyRepeatRate;
|
||||
int32_t keyRepeatDelay;
|
||||
int keyRepeatScancode;
|
||||
|
||||
char* clipboardString;
|
||||
size_t clipboardSize;
|
||||
char* clipboardSendString;
|
||||
size_t clipboardSendSize;
|
||||
int timerfd;
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char keynames[GLFW_KEY_LAST + 1][5];
|
||||
|
@ -321,12 +340,12 @@ typedef struct _GLFWlibraryWayland
|
|||
|
||||
struct xkb_compose_state* composeState;
|
||||
|
||||
xkb_mod_mask_t controlMask;
|
||||
xkb_mod_mask_t altMask;
|
||||
xkb_mod_mask_t shiftMask;
|
||||
xkb_mod_mask_t superMask;
|
||||
xkb_mod_mask_t capsLockMask;
|
||||
xkb_mod_mask_t numLockMask;
|
||||
xkb_mod_index_t controlIndex;
|
||||
xkb_mod_index_t altIndex;
|
||||
xkb_mod_index_t shiftIndex;
|
||||
xkb_mod_index_t superIndex;
|
||||
xkb_mod_index_t capsLockIndex;
|
||||
xkb_mod_index_t numLockIndex;
|
||||
unsigned int modifiers;
|
||||
|
||||
PFN_xkb_context_new context_new;
|
||||
|
@ -340,8 +359,8 @@ typedef struct _GLFWlibraryWayland
|
|||
PFN_xkb_state_unref state_unref;
|
||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||
PFN_xkb_state_update_mask state_update_mask;
|
||||
PFN_xkb_state_serialize_mods state_serialize_mods;
|
||||
PFN_xkb_state_key_get_layout state_key_get_layout;
|
||||
PFN_xkb_state_mod_index_is_active state_mod_index_is_active;
|
||||
|
||||
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
||||
PFN_xkb_compose_table_unref compose_table_unref;
|
||||
|
@ -423,7 +442,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform);
|
|||
int _glfwInitWayland(void);
|
||||
void _glfwTerminateWayland(void);
|
||||
|
||||
int _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyWindowWayland(_GLFWwindow* window);
|
||||
void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title);
|
||||
void _glfwSetWindowIconWayland(_GLFWwindow* window, int count, const GLFWimage* images);
|
||||
|
@ -444,12 +463,12 @@ void _glfwHideWindowWayland(_GLFWwindow* window);
|
|||
void _glfwRequestWindowAttentionWayland(_GLFWwindow* window);
|
||||
void _glfwFocusWindowWayland(_GLFWwindow* window);
|
||||
void _glfwSetWindowMonitorWayland(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
|
||||
int _glfwWindowFocusedWayland(_GLFWwindow* window);
|
||||
int _glfwWindowIconifiedWayland(_GLFWwindow* window);
|
||||
int _glfwWindowVisibleWayland(_GLFWwindow* window);
|
||||
int _glfwWindowMaximizedWayland(_GLFWwindow* window);
|
||||
int _glfwWindowHoveredWayland(_GLFWwindow* window);
|
||||
int _glfwFramebufferTransparentWayland(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowFocusedWayland(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowIconifiedWayland(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowVisibleWayland(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window);
|
||||
GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window);
|
||||
void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowFloatingWayland(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
@ -457,7 +476,7 @@ float _glfwGetWindowOpacityWayland(_GLFWwindow* window);
|
|||
void _glfwSetWindowOpacityWayland(_GLFWwindow* window, float opacity);
|
||||
void _glfwSetWindowMousePassthroughWayland(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
||||
void _glfwSetRawMouseMotionWayland(_GLFWwindow *window, GLFWbool enabled);
|
||||
void _glfwSetRawMouseMotionWayland(_GLFWwindow* window, GLFWbool enabled);
|
||||
GLFWbool _glfwRawMouseMotionSupportedWayland(void);
|
||||
|
||||
void _glfwPollEventsWayland(void);
|
||||
|
@ -470,8 +489,8 @@ void _glfwSetCursorPosWayland(_GLFWwindow* window, double xpos, double ypos);
|
|||
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameWayland(int scancode);
|
||||
int _glfwGetKeyScancodeWayland(int key);
|
||||
int _glfwCreateCursorWayland(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
int _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape);
|
||||
GLFWbool _glfwCreateCursorWayland(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape);
|
||||
void _glfwDestroyCursorWayland(_GLFWcursor* cursor);
|
||||
void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
void _glfwSetClipboardStringWayland(const char* string);
|
||||
|
@ -482,7 +501,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayWayland(void);
|
|||
EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window);
|
||||
|
||||
void _glfwGetRequiredInstanceExtensionsWayland(char** extensions);
|
||||
int _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
void _glfwFreeMonitorWayland(_GLFWmonitor* monitor);
|
||||
|
@ -495,5 +514,8 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
|||
void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);
|
||||
void _glfwUpdateContentScaleWayland(_GLFWwindow* window);
|
||||
|
||||
void _glfwAddSeatListenerWayland(struct wl_seat* seat);
|
||||
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,12 +29,17 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <locale.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// Translate the X11 KeySyms for a key to a GLFW key code
|
||||
|
@ -601,7 +606,7 @@ static void detectEWMH(void)
|
|||
//
|
||||
static GLFWbool initExtensions(void)
|
||||
{
|
||||
#if defined(__OpenBSD__)
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so");
|
||||
#else
|
||||
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1");
|
||||
|
@ -625,7 +630,7 @@ static GLFWbool initExtensions(void)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so");
|
||||
#else
|
||||
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6");
|
||||
|
@ -657,7 +662,7 @@ static GLFWbool initExtensions(void)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so");
|
||||
#else
|
||||
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2");
|
||||
|
@ -751,7 +756,7 @@ static GLFWbool initExtensions(void)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so");
|
||||
#else
|
||||
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1");
|
||||
|
@ -774,7 +779,7 @@ static GLFWbool initExtensions(void)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so");
|
||||
#else
|
||||
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1");
|
||||
|
@ -829,7 +834,7 @@ static GLFWbool initExtensions(void)
|
|||
{
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so");
|
||||
#else
|
||||
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1");
|
||||
|
@ -844,7 +849,7 @@ static GLFWbool initExtensions(void)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so");
|
||||
#else
|
||||
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1");
|
||||
|
@ -873,7 +878,7 @@ static GLFWbool initExtensions(void)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so");
|
||||
#else
|
||||
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6");
|
||||
|
@ -1042,6 +1047,37 @@ static Window createHelperWindow(void)
|
|||
CWEventMask, &wa);
|
||||
}
|
||||
|
||||
// Create the pipe for empty events without assumuing the OS has pipe2(2)
|
||||
//
|
||||
static GLFWbool createEmptyEventPipe(void)
|
||||
{
|
||||
if (pipe(_glfw.x11.emptyEventPipe) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to create empty event pipe: %s",
|
||||
strerror(errno));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0);
|
||||
const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0);
|
||||
|
||||
if (sf == -1 || df == -1 ||
|
||||
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 ||
|
||||
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to set flags for empty event pipe: %s",
|
||||
strerror(errno));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// X error handler
|
||||
//
|
||||
static int errorHandler(Display *display, XErrorEvent* event)
|
||||
|
@ -1062,8 +1098,9 @@ static int errorHandler(Display *display, XErrorEvent* event)
|
|||
//
|
||||
void _glfwGrabErrorHandlerX11(void)
|
||||
{
|
||||
assert(_glfw.x11.errorHandler == NULL);
|
||||
_glfw.x11.errorCode = Success;
|
||||
XSetErrorHandler(errorHandler);
|
||||
_glfw.x11.errorHandler = XSetErrorHandler(errorHandler);
|
||||
}
|
||||
|
||||
// Clears the X error handler callback
|
||||
|
@ -1072,7 +1109,8 @@ void _glfwReleaseErrorHandlerX11(void)
|
|||
{
|
||||
// Synchronize to make sure all commands are processed
|
||||
XSync(_glfw.x11.display, False);
|
||||
XSetErrorHandler(NULL);
|
||||
XSetErrorHandler(_glfw.x11.errorHandler);
|
||||
_glfw.x11.errorHandler = NULL;
|
||||
}
|
||||
|
||||
// Reports the specified error, appending information about the last X error
|
||||
|
@ -1146,7 +1184,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
|
|||
_glfwGetKeyScancodeX11,
|
||||
_glfwSetClipboardStringX11,
|
||||
_glfwGetClipboardStringX11,
|
||||
#if defined(__linux__)
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
_glfwInitJoysticksLinux,
|
||||
_glfwTerminateJoysticksLinux,
|
||||
_glfwPollJoystickLinux,
|
||||
|
@ -1221,7 +1259,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
|
|||
|
||||
#if defined(__CYGWIN__)
|
||||
void* module = _glfwPlatformLoadModule("libX11-6.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
void* module = _glfwPlatformLoadModule("libX11.so");
|
||||
#else
|
||||
void* module = _glfwPlatformLoadModule("libX11.so.6");
|
||||
|
@ -1491,6 +1529,9 @@ int _glfwInitX11(void)
|
|||
|
||||
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
||||
|
||||
if (!createEmptyEventPipe())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!initExtensions())
|
||||
return GLFW_FALSE;
|
||||
|
||||
|
@ -1594,6 +1635,7 @@ void _glfwTerminateX11(void)
|
|||
_glfw.x11.xi.handle = NULL;
|
||||
}
|
||||
|
||||
_glfwTerminateOSMesa();
|
||||
// NOTE: These need to be unloaded after XCloseDisplay, as they register
|
||||
// cleanup callbacks that get called by that function
|
||||
_glfwTerminateEGL();
|
||||
|
@ -1604,5 +1646,13 @@ void _glfwTerminateX11(void)
|
|||
_glfwPlatformFreeModule(_glfw.x11.xlib.handle);
|
||||
_glfw.x11.xlib.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
|
||||
{
|
||||
close(_glfw.x11.emptyEventPipe[0]);
|
||||
close(_glfw.x11.emptyEventPipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _GLFW_X11
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -614,3 +616,5 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
|
|||
return monitor->x11.output;
|
||||
}
|
||||
|
||||
#endif // _GLFW_X11
|
||||
|
||||
|
|
|
@ -453,6 +453,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSur
|
|||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
|
||||
|
||||
#include "xkb_unicode.h"
|
||||
#include "posix_poll.h"
|
||||
|
||||
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
|
||||
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
|
||||
|
@ -479,7 +480,6 @@ typedef struct _GLFWlibraryGLX
|
|||
int eventBase;
|
||||
int errorBase;
|
||||
|
||||
// dlopen handle for libGL.so.1
|
||||
void* handle;
|
||||
|
||||
// GLX 1.3 functions
|
||||
|
@ -566,6 +566,8 @@ typedef struct _GLFWlibraryX11
|
|||
XContext context;
|
||||
// XIM input method
|
||||
XIM im;
|
||||
// The previous X error handler, to be restored later
|
||||
XErrorHandler errorHandler;
|
||||
// Most recent error code received by X error handler
|
||||
int errorCode;
|
||||
// Primary selection string (while the primary selection is owned)
|
||||
|
@ -582,6 +584,7 @@ typedef struct _GLFWlibraryX11
|
|||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
int emptyEventPipe[2];
|
||||
|
||||
// Window manager atoms
|
||||
Atom NET_SUPPORTED;
|
||||
|
@ -898,7 +901,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform);
|
|||
int _glfwInitX11(void);
|
||||
void _glfwTerminateX11(void);
|
||||
|
||||
int _glfwCreateWindowX11(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
GLFWbool _glfwCreateWindowX11(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyWindowX11(_GLFWwindow* window);
|
||||
void _glfwSetWindowTitleX11(_GLFWwindow* window, const char* title);
|
||||
void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* images);
|
||||
|
@ -919,12 +922,12 @@ void _glfwHideWindowX11(_GLFWwindow* window);
|
|||
void _glfwRequestWindowAttentionX11(_GLFWwindow* window);
|
||||
void _glfwFocusWindowX11(_GLFWwindow* window);
|
||||
void _glfwSetWindowMonitorX11(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
|
||||
int _glfwWindowFocusedX11(_GLFWwindow* window);
|
||||
int _glfwWindowIconifiedX11(_GLFWwindow* window);
|
||||
int _glfwWindowVisibleX11(_GLFWwindow* window);
|
||||
int _glfwWindowMaximizedX11(_GLFWwindow* window);
|
||||
int _glfwWindowHoveredX11(_GLFWwindow* window);
|
||||
int _glfwFramebufferTransparentX11(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowFocusedX11(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowIconifiedX11(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowVisibleX11(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowMaximizedX11(_GLFWwindow* window);
|
||||
GLFWbool _glfwWindowHoveredX11(_GLFWwindow* window);
|
||||
GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow* window);
|
||||
void _glfwSetWindowResizableX11(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowDecoratedX11(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
@ -945,8 +948,8 @@ void _glfwSetCursorPosX11(_GLFWwindow* window, double xpos, double ypos);
|
|||
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameX11(int scancode);
|
||||
int _glfwGetKeyScancodeX11(int key);
|
||||
int _glfwCreateCursorX11(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
int _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape);
|
||||
GLFWbool _glfwCreateCursorX11(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape);
|
||||
void _glfwDestroyCursorX11(_GLFWcursor* cursor);
|
||||
void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
void _glfwSetClipboardStringX11(const char* string);
|
||||
|
@ -957,7 +960,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayX11(void);
|
|||
EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow* window);
|
||||
|
||||
void _glfwGetRequiredInstanceExtensionsX11(char** extensions);
|
||||
int _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
void _glfwFreeMonitorX11(_GLFWmonitor* monitor);
|
||||
|
|
|
@ -29,10 +29,12 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xmd.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -56,50 +58,79 @@
|
|||
|
||||
#define _GLFW_XDND_VERSION 5
|
||||
|
||||
|
||||
// Wait for data to arrive using select
|
||||
// Wait for event data to arrive on the X11 display socket
|
||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||
// covers GLX functions
|
||||
//
|
||||
static GLFWbool waitForEvent(double* timeout)
|
||||
static GLFWbool waitForX11Event(double* timeout)
|
||||
{
|
||||
fd_set fds;
|
||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
||||
int count = fd + 1;
|
||||
struct pollfd fd = { ConnectionNumber(_glfw.x11.display), POLLIN };
|
||||
|
||||
#if defined(__linux__)
|
||||
if (_glfw.linjs.inotify > fd)
|
||||
count = _glfw.linjs.inotify + 1;
|
||||
while (!XPending(_glfw.x11.display))
|
||||
{
|
||||
if (!_glfwPollPOSIX(&fd, 1, timeout))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Wait for event data to arrive on any event file descriptor
|
||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||
// covers GLX functions
|
||||
//
|
||||
static GLFWbool waitForAnyEvent(double* timeout)
|
||||
{
|
||||
nfds_t count = 2;
|
||||
struct pollfd fds[3] =
|
||||
{
|
||||
{ ConnectionNumber(_glfw.x11.display), POLLIN },
|
||||
{ _glfw.x11.emptyEventPipe[0], POLLIN }
|
||||
};
|
||||
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
if (_glfw.joysticksInitialized)
|
||||
fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };
|
||||
#endif
|
||||
|
||||
while (!XPending(_glfw.x11.display))
|
||||
{
|
||||
if (!_glfwPollPOSIX(fds, count, timeout))
|
||||
return GLFW_FALSE;
|
||||
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
if (fds[i].revents & POLLIN)
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Writes a byte to the empty event pipe
|
||||
//
|
||||
static void writeEmptyEvent(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
#if defined(__linux__)
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
FD_SET(_glfw.linjs.inotify, &fds);
|
||||
#endif
|
||||
const char byte = 0;
|
||||
const ssize_t result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);
|
||||
if (result == 1 || (result == -1 && errno != EINTR))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
const long seconds = (long) *timeout;
|
||||
const long microseconds = (long) ((*timeout - seconds) * 1e6);
|
||||
struct timeval tv = { seconds, microseconds };
|
||||
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||
|
||||
const int result = select(count, &fds, NULL, NULL, &tv);
|
||||
const int error = errno;
|
||||
|
||||
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||
(double) _glfwPlatformGetTimerFrequency();
|
||||
|
||||
if (result > 0)
|
||||
return GLFW_TRUE;
|
||||
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
|
||||
return GLFW_TRUE;
|
||||
// Drains available data from the empty event pipe
|
||||
//
|
||||
static void drainEmptyEvents(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
char dummy[64];
|
||||
const ssize_t result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));
|
||||
if (result == -1 && errno != EINTR)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +147,7 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
|||
VisibilityNotify,
|
||||
&dummy))
|
||||
{
|
||||
if (!waitForEvent(&timeout))
|
||||
if (!waitForX11Event(&timeout))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
|
@ -241,6 +272,11 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
|
|||
{
|
||||
XSizeHints* hints = XAllocSizeHints();
|
||||
|
||||
long supplied;
|
||||
XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied);
|
||||
|
||||
hints->flags &= ~(PMinSize | PMaxSize | PAspect);
|
||||
|
||||
if (!window->monitor)
|
||||
{
|
||||
if (window->resizable)
|
||||
|
@ -277,9 +313,6 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
|
|||
}
|
||||
}
|
||||
|
||||
hints->flags |= PWinGravity;
|
||||
hints->win_gravity = StaticGravity;
|
||||
|
||||
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
|
||||
XFree(hints);
|
||||
}
|
||||
|
@ -378,57 +411,6 @@ static void updateWindowMode(_GLFWwindow* window)
|
|||
}
|
||||
}
|
||||
|
||||
// Splits and translates a text/uri-list into separate file paths
|
||||
// NOTE: This function destroys the provided string
|
||||
//
|
||||
static char** parseUriList(char* text, int* count)
|
||||
{
|
||||
const char* prefix = "file://";
|
||||
char** paths = NULL;
|
||||
char* line;
|
||||
|
||||
*count = 0;
|
||||
|
||||
while ((line = strtok(text, "\r\n")))
|
||||
{
|
||||
text = NULL;
|
||||
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
if (strncmp(line, prefix, strlen(prefix)) == 0)
|
||||
{
|
||||
line += strlen(prefix);
|
||||
// TODO: Validate hostname
|
||||
while (*line != '/')
|
||||
line++;
|
||||
}
|
||||
|
||||
(*count)++;
|
||||
|
||||
char* path = _glfw_calloc(strlen(line) + 1, 1);
|
||||
paths = _glfw_realloc(paths, *count * sizeof(char*));
|
||||
paths[*count - 1] = path;
|
||||
|
||||
while (*line)
|
||||
{
|
||||
if (line[0] == '%' && line[1] && line[2])
|
||||
{
|
||||
const char digits[3] = { line[1], line[2], '\0' };
|
||||
*path = strtol(digits, NULL, 16);
|
||||
line += 2;
|
||||
}
|
||||
else
|
||||
*path = *line;
|
||||
|
||||
path++;
|
||||
line++;
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
// Decode a Unicode code point from a UTF-8 stream
|
||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||
//
|
||||
|
@ -475,7 +457,8 @@ static char* convertLatin1toUTF8(const char* source)
|
|||
//
|
||||
static void updateCursorImage(_GLFWwindow* window)
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL ||
|
||||
window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
{
|
||||
if (window->cursor)
|
||||
{
|
||||
|
@ -492,6 +475,25 @@ static void updateCursorImage(_GLFWwindow* window)
|
|||
}
|
||||
}
|
||||
|
||||
// Grabs the cursor and confines it to the window
|
||||
//
|
||||
static void captureCursor(_GLFWwindow* window)
|
||||
{
|
||||
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
|
||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
window->x11.handle,
|
||||
None,
|
||||
CurrentTime);
|
||||
}
|
||||
|
||||
// Ungrabs the cursor
|
||||
//
|
||||
static void releaseCursor(void)
|
||||
{
|
||||
XUngrabPointer(_glfw.x11.display, CurrentTime);
|
||||
}
|
||||
|
||||
// Enable XI2 raw mouse motion events
|
||||
//
|
||||
static void enableRawMouseMotion(_GLFWwindow* window)
|
||||
|
@ -534,12 +536,7 @@ static void disableCursor(_GLFWwindow* window)
|
|||
&_glfw.x11.restoreCursorPosY);
|
||||
updateCursorImage(window);
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
|
||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
window->x11.handle,
|
||||
_glfw.x11.hiddenCursorHandle,
|
||||
CurrentTime);
|
||||
captureCursor(window);
|
||||
}
|
||||
|
||||
// Exit disabled cursor mode for the specified window
|
||||
|
@ -550,7 +547,7 @@ static void enableCursor(_GLFWwindow* window)
|
|||
disableRawMouseMotion(window);
|
||||
|
||||
_glfw.x11.disabledCursorWindow = NULL;
|
||||
XUngrabPointer(_glfw.x11.display, CurrentTime);
|
||||
releaseCursor();
|
||||
_glfwSetCursorPosX11(window,
|
||||
_glfw.x11.restoreCursorPosX,
|
||||
_glfw.x11.restoreCursorPosY);
|
||||
|
@ -580,6 +577,14 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
height *= _glfw.x11.contentScaleY;
|
||||
}
|
||||
|
||||
int xpos = 0, ypos = 0;
|
||||
|
||||
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
|
||||
{
|
||||
xpos = wndconfig->xpos;
|
||||
ypos = wndconfig->ypos;
|
||||
}
|
||||
|
||||
// Create a colormap based on the visual used by the current context
|
||||
window->x11.colormap = XCreateColormap(_glfw.x11.display,
|
||||
_glfw.x11.root,
|
||||
|
@ -600,7 +605,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
window->x11.parent = _glfw.x11.root;
|
||||
window->x11.handle = XCreateWindow(_glfw.x11.display,
|
||||
_glfw.x11.root,
|
||||
0, 0, // Position
|
||||
xpos, ypos,
|
||||
width, height,
|
||||
0, // Border width
|
||||
depth, // Color depth
|
||||
|
@ -703,7 +708,37 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||
XFree(hints);
|
||||
}
|
||||
|
||||
updateNormalHints(window, width, height);
|
||||
// Set ICCCM WM_NORMAL_HINTS property
|
||||
{
|
||||
XSizeHints* hints = XAllocSizeHints();
|
||||
if (!hints)
|
||||
{
|
||||
_glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!wndconfig->resizable)
|
||||
{
|
||||
hints->flags |= (PMinSize | PMaxSize);
|
||||
hints->min_width = hints->max_width = width;
|
||||
hints->min_height = hints->max_height = height;
|
||||
}
|
||||
|
||||
// HACK: Explicitly setting PPosition to any value causes some WMs, notably
|
||||
// Compiz and Metacity, to honor the position of unmapped windows
|
||||
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
|
||||
{
|
||||
hints->flags |= PPosition;
|
||||
hints->x = 0;
|
||||
hints->y = 0;
|
||||
}
|
||||
|
||||
hints->flags |= PWinGravity;
|
||||
hints->win_gravity = StaticGravity;
|
||||
|
||||
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
|
||||
XFree(hints);
|
||||
}
|
||||
|
||||
// Set ICCCM WM_CLASS property
|
||||
{
|
||||
|
@ -887,20 +922,6 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
|||
return None;
|
||||
}
|
||||
|
||||
static void handleSelectionClear(XEvent* event)
|
||||
{
|
||||
if (event->xselectionclear.selection == _glfw.x11.PRIMARY)
|
||||
{
|
||||
_glfw_free(_glfw.x11.primarySelectionString);
|
||||
_glfw.x11.primarySelectionString = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfw_free(_glfw.x11.clipboardString);
|
||||
_glfw.x11.clipboardString = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleSelectionRequest(XEvent* event)
|
||||
{
|
||||
const XSelectionRequestEvent* request = &event->xselectionrequest;
|
||||
|
@ -958,7 +979,7 @@ static const char* getSelectionString(Atom selection)
|
|||
SelectionNotify,
|
||||
¬ification))
|
||||
{
|
||||
waitForEvent(NULL);
|
||||
waitForX11Event(NULL);
|
||||
}
|
||||
|
||||
if (notification.xselection.property == None)
|
||||
|
@ -994,7 +1015,7 @@ static const char* getSelectionString(Atom selection)
|
|||
isSelPropNewValueNotify,
|
||||
(XPointer) ¬ification))
|
||||
{
|
||||
waitForEvent(NULL);
|
||||
waitForX11Event(NULL);
|
||||
}
|
||||
|
||||
XFree(data);
|
||||
|
@ -1021,13 +1042,16 @@ static const char* getSelectionString(Atom selection)
|
|||
|
||||
if (!itemCount)
|
||||
{
|
||||
if (targets[i] == XA_STRING)
|
||||
if (string)
|
||||
{
|
||||
*selectionString = convertLatin1toUTF8(string);
|
||||
_glfw_free(string);
|
||||
if (targets[i] == XA_STRING)
|
||||
{
|
||||
*selectionString = convertLatin1toUTF8(string);
|
||||
_glfw_free(string);
|
||||
}
|
||||
else
|
||||
*selectionString = string;
|
||||
}
|
||||
else
|
||||
*selectionString = string;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1193,12 +1217,7 @@ static void processEvent(XEvent *event)
|
|||
return;
|
||||
}
|
||||
|
||||
if (event->type == SelectionClear)
|
||||
{
|
||||
handleSelectionClear(event);
|
||||
return;
|
||||
}
|
||||
else if (event->type == SelectionRequest)
|
||||
if (event->type == SelectionRequest)
|
||||
{
|
||||
handleSelectionRequest(event);
|
||||
return;
|
||||
|
@ -1238,7 +1257,7 @@ static void processEvent(XEvent *event)
|
|||
// (the server never sends a timestamp of zero)
|
||||
// NOTE: Timestamp difference is compared to handle wrap-around
|
||||
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
|
||||
if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31)))
|
||||
if (diff == event->xkey.time || (diff > 0 && diff < ((Time)1 << 31)))
|
||||
{
|
||||
if (keycode)
|
||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||
|
@ -1686,7 +1705,7 @@ static void processEvent(XEvent *event)
|
|||
if (result)
|
||||
{
|
||||
int count;
|
||||
char** paths = parseUriList(data, &count);
|
||||
char** paths = _glfwParseUriList(data, &count);
|
||||
|
||||
_glfwInputDrop(window, count, (const char**) paths);
|
||||
|
||||
|
@ -1729,6 +1748,8 @@ static void processEvent(XEvent *event)
|
|||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
disableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
captureCursor(window);
|
||||
|
||||
if (window->x11.ic)
|
||||
XSetICFocus(window->x11.ic);
|
||||
|
@ -1749,6 +1770,8 @@ static void processEvent(XEvent *event)
|
|||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
enableCursor(window);
|
||||
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
releaseCursor();
|
||||
|
||||
if (window->x11.ic)
|
||||
XUnsetICFocus(window->x11.ic);
|
||||
|
@ -1875,10 +1898,6 @@ void _glfwPushSelectionToManagerX11(void)
|
|||
handleSelectionRequest(&event);
|
||||
break;
|
||||
|
||||
case SelectionClear:
|
||||
handleSelectionClear(&event);
|
||||
break;
|
||||
|
||||
case SelectionNotify:
|
||||
{
|
||||
if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
|
||||
|
@ -1896,7 +1915,7 @@ void _glfwPushSelectionToManagerX11(void)
|
|||
}
|
||||
}
|
||||
|
||||
waitForEvent(NULL);
|
||||
waitForX11Event(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1937,10 +1956,10 @@ void _glfwCreateInputContextX11(_GLFWwindow* window)
|
|||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwCreateWindowX11(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
Visual* visual = NULL;
|
||||
int depth;
|
||||
|
@ -1994,13 +2013,31 @@ int _glfwCreateWindowX11(_GLFWwindow* window,
|
|||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwRefreshContextAttribs(window, ctxconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (wndconfig->mousePassthrough)
|
||||
_glfwSetWindowMousePassthroughX11(window, GLFW_TRUE);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
_glfwShowWindowX11(window);
|
||||
updateWindowMode(window);
|
||||
acquireMonitor(window);
|
||||
|
||||
if (wndconfig->centerCursor)
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
_glfwShowWindowX11(window);
|
||||
if (wndconfig->focused)
|
||||
_glfwFocusWindowX11(window);
|
||||
}
|
||||
}
|
||||
|
||||
XFlush(_glfw.x11.display);
|
||||
|
@ -2010,7 +2047,7 @@ int _glfwCreateWindowX11(_GLFWwindow* window,
|
|||
void _glfwDestroyWindowX11(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.x11.disabledCursorWindow == window)
|
||||
_glfw.x11.disabledCursorWindow = NULL;
|
||||
enableCursor(window);
|
||||
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
|
@ -2238,7 +2275,7 @@ void _glfwGetWindowFrameSizeX11(_GLFWwindow* window,
|
|||
isFrameExtentsEvent,
|
||||
(XPointer) window))
|
||||
{
|
||||
if (!waitForEvent(&timeout))
|
||||
if (!waitForX11Event(&timeout))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
||||
|
@ -2486,7 +2523,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
|
|||
XFlush(_glfw.x11.display);
|
||||
}
|
||||
|
||||
int _glfwWindowFocusedX11(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowFocusedX11(_GLFWwindow* window)
|
||||
{
|
||||
Window focused;
|
||||
int state;
|
||||
|
@ -2495,19 +2532,19 @@ int _glfwWindowFocusedX11(_GLFWwindow* window)
|
|||
return window->x11.handle == focused;
|
||||
}
|
||||
|
||||
int _glfwWindowIconifiedX11(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowIconifiedX11(_GLFWwindow* window)
|
||||
{
|
||||
return getWindowState(window) == IconicState;
|
||||
}
|
||||
|
||||
int _glfwWindowVisibleX11(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowVisibleX11(_GLFWwindow* window)
|
||||
{
|
||||
XWindowAttributes wa;
|
||||
XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);
|
||||
return wa.map_state == IsViewable;
|
||||
}
|
||||
|
||||
int _glfwWindowMaximizedX11(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowMaximizedX11(_GLFWwindow* window)
|
||||
{
|
||||
Atom* states;
|
||||
GLFWbool maximized = GLFW_FALSE;
|
||||
|
@ -2541,7 +2578,7 @@ int _glfwWindowMaximizedX11(_GLFWwindow* window)
|
|||
return maximized;
|
||||
}
|
||||
|
||||
int _glfwWindowHoveredX11(_GLFWwindow* window)
|
||||
GLFWbool _glfwWindowHoveredX11(_GLFWwindow* window)
|
||||
{
|
||||
Window w = _glfw.x11.root;
|
||||
while (w)
|
||||
|
@ -2569,7 +2606,7 @@ int _glfwWindowHoveredX11(_GLFWwindow* window)
|
|||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwFramebufferTransparentX11(_GLFWwindow* window)
|
||||
GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->x11.transparent)
|
||||
return GLFW_FALSE;
|
||||
|
@ -2744,9 +2781,9 @@ GLFWbool _glfwRawMouseMotionSupportedX11(void)
|
|||
|
||||
void _glfwPollEventsX11(void)
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
drainEmptyEvents();
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
|
||||
if (_glfw.joysticksInitialized)
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
#endif
|
||||
|
@ -2759,7 +2796,7 @@ void _glfwPollEventsX11(void)
|
|||
processEvent(&event);
|
||||
}
|
||||
|
||||
window = _glfw.x11.disabledCursorWindow;
|
||||
_GLFWwindow* window = _glfw.x11.disabledCursorWindow;
|
||||
if (window)
|
||||
{
|
||||
int width, height;
|
||||
|
@ -2779,32 +2816,19 @@ void _glfwPollEventsX11(void)
|
|||
|
||||
void _glfwWaitEventsX11(void)
|
||||
{
|
||||
while (!XPending(_glfw.x11.display))
|
||||
waitForEvent(NULL);
|
||||
|
||||
waitForAnyEvent(NULL);
|
||||
_glfwPollEventsX11();
|
||||
}
|
||||
|
||||
void _glfwWaitEventsTimeoutX11(double timeout)
|
||||
{
|
||||
while (!XPending(_glfw.x11.display))
|
||||
{
|
||||
if (!waitForEvent(&timeout))
|
||||
break;
|
||||
}
|
||||
|
||||
waitForAnyEvent(&timeout);
|
||||
_glfwPollEventsX11();
|
||||
}
|
||||
|
||||
void _glfwPostEmptyEventX11(void)
|
||||
{
|
||||
XEvent event = { ClientMessage };
|
||||
event.xclient.window = _glfw.x11.helperWindowHandle;
|
||||
event.xclient.format = 32; // Data is 32-bit longs
|
||||
event.xclient.message_type = _glfw.x11.NULL_;
|
||||
|
||||
XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
|
||||
XFlush(_glfw.x11.display);
|
||||
writeEmptyEvent();
|
||||
}
|
||||
|
||||
void _glfwGetCursorPosX11(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
|
@ -2837,16 +2861,40 @@ void _glfwSetCursorPosX11(_GLFWwindow* window, double x, double y)
|
|||
|
||||
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode)
|
||||
{
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
if (_glfwWindowFocusedX11(window))
|
||||
{
|
||||
if (_glfwWindowFocusedX11(window))
|
||||
disableCursor(window);
|
||||
}
|
||||
else if (_glfw.x11.disabledCursorWindow == window)
|
||||
enableCursor(window);
|
||||
else
|
||||
updateCursorImage(window);
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfwGetCursorPosX11(window,
|
||||
&_glfw.x11.restoreCursorPosX,
|
||||
&_glfw.x11.restoreCursorPosY);
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
if (window->rawMouseMotion)
|
||||
enableRawMouseMotion(window);
|
||||
}
|
||||
else if (_glfw.x11.disabledCursorWindow == window)
|
||||
{
|
||||
if (window->rawMouseMotion)
|
||||
disableRawMouseMotion(window);
|
||||
}
|
||||
|
||||
if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED)
|
||||
captureCursor(window);
|
||||
else
|
||||
releaseCursor();
|
||||
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
_glfw.x11.disabledCursorWindow = window;
|
||||
else if (_glfw.x11.disabledCursorWindow == window)
|
||||
{
|
||||
_glfw.x11.disabledCursorWindow = NULL;
|
||||
_glfwSetCursorPosX11(window,
|
||||
_glfw.x11.restoreCursorPosX,
|
||||
_glfw.x11.restoreCursorPosY);
|
||||
}
|
||||
}
|
||||
|
||||
updateCursorImage(window);
|
||||
XFlush(_glfw.x11.display);
|
||||
}
|
||||
|
||||
|
@ -2885,9 +2933,9 @@ int _glfwGetKeyScancodeX11(int key)
|
|||
return _glfw.x11.scancodes[key];
|
||||
}
|
||||
|
||||
int _glfwCreateCursorX11(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
GLFWbool _glfwCreateCursorX11(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
cursor->x11.handle = _glfwCreateNativeCursorX11(image, xhot, yhot);
|
||||
if (!cursor->x11.handle)
|
||||
|
@ -2896,7 +2944,7 @@ int _glfwCreateCursorX11(_GLFWcursor* cursor,
|
|||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
int _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape)
|
||||
GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
if (_glfw.x11.xcursor.handle)
|
||||
{
|
||||
|
@ -3002,7 +3050,8 @@ void _glfwDestroyCursorX11(_GLFWcursor* cursor)
|
|||
|
||||
void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL ||
|
||||
window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||
{
|
||||
updateCursorImage(window);
|
||||
XFlush(_glfw.x11.display);
|
||||
|
@ -3103,9 +3152,9 @@ void _glfwGetRequiredInstanceExtensionsX11(char** extensions)
|
|||
extensions[1] = "VK_KHR_xlib_surface";
|
||||
}
|
||||
|
||||
int _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display,
|
||||
_glfw.x11.screen));
|
||||
|
@ -3302,3 +3351,5 @@ GLFWAPI const char* glfwGetX11SelectionString(void)
|
|||
return getSelectionString(_glfw.x11.PRIMARY);
|
||||
}
|
||||
|
||||
#endif // _GLFW_X11
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
|
||||
|
||||
/*
|
||||
* Marcus: This code was originally written by Markus G. Kuhn.
|
||||
|
@ -940,3 +941,5 @@ uint32_t _glfwKeySym2Unicode(unsigned int keysym)
|
|||
return GLFW_INVALID_CODEPOINT;
|
||||
}
|
||||
|
||||
#endif // _GLFW_WAYLAND or _GLFW_X11
|
||||
|
||||
|
|
Loading…
Reference in New Issue